<commit_before>#ifndef ARABICA_XSLT_FUNCTIONS_HPP
#define ARABICA_XSLT_FUNCTIONS_HPP

#include <DOM/SAX2DOM/SAX2DOM.hpp>
#include <SAX/helpers/CatchErrorHandler.hpp>

namespace Arabica
{
namespace XSLT
{

// node-set document(object, node-set?)
class DocumentFunction : public Arabica::XPath::XPathFunction<std::string>
{
  typedef Arabica::XPath::XPathFunction<std::string> baseT;

public:
  DocumentFunction(const std::string& currentBase, 
                   const std::vector<Arabica::XPath::XPathExpression<std::string> >& args) :
      Arabica::XPath::XPathFunction<std::string>(1, 2, args),
      baseURI_(currentBase)
  { } 

  virtual Arabica::XPath::ValueType type() const { return Arabica::XPath::NODE_SET; }

  virtual Arabica::XPath::XPathValue_impl<std::string>* evaluate(const DOM::Node<std::string>& context,
                                            const Arabica::XPath::ExecutionContext<std::string>& executionContext) const
  {
    Arabica::XPath::NodeSet<std::string> nodes;
     
    Arabica::XPath::XPathValuePtr<std::string> a1 = arg(0, context, executionContext);
    if(a1->type() != Arabica::XPath::NODE_SET)
      load_document(a1->asString(), nodes);
    else 
      throw Arabica::XPath::UnsupportedException("node-set arg version of document()");
    return new Arabica::XPath::NodeSetValue<std::string>(nodes);
  } // evaluate

private:
  void load_document(const std::string& location,
                     Arabica::XPath::NodeSet<std::string>& nodes) const
  {
    SAX2DOM::Parser<std::string> domParser;
    SAX::CatchErrorHandler<std::string> eh;
    domParser.setErrorHandler(eh);

    Arabica::io::URI base(baseURI_);
    Arabica::io::URI absolute(base, location);

    SAX::InputSource<std::string> is(absolute.as_string());
    domParser.parse(is);

    if(!eh.errorsReported())
        nodes.push_back(domParser.getDocument());
    else
        std::cerr << eh.errors() << std::endl;
  } // load_document

  std::string baseURI_; 
}; // DocumentFunction

// node-set key(string, object)
// string format-number(number, string, string?)

// node-set current()
class CurrentFunction : public Arabica::XPath::XPathFunction<std::string>
{
  typedef Arabica::XPath::XPathFunction<std::string> baseT;

public:<commit_msg>Skinned up skeleton implementation of key() function.  Doesn't do anything yet though :)<commit_after>#ifndef ARABICA_XSLT_FUNCTIONS_HPP
#define ARABICA_XSLT_FUNCTIONS_HPP

#include <DOM/SAX2DOM/SAX2DOM.hpp>
#include <SAX/helpers/CatchErrorHandler.hpp>

namespace Arabica
{
namespace XSLT
{

// node-set document(object, node-set?)
class DocumentFunction : public Arabica::XPath::XPathFunction<std::string>
{
  typedef Arabica::XPath::XPathFunction<std::string> baseT;

public:
  DocumentFunction(const std::string& currentBase, 
                   const std::vector<Arabica::XPath::XPathExpression<std::string> >& args) :
      Arabica::XPath::XPathFunction<std::string>(1, 2, args),
      baseURI_(currentBase)
  { } 

  virtual Arabica::XPath::ValueType type() const { return Arabica::XPath::NODE_SET; }

  virtual Arabica::XPath::XPathValue_impl<std::string>* evaluate(const DOM::Node<std::string>& context,
                                            const Arabica::XPath::ExecutionContext<std::string>& executionContext) const
  {
    Arabica::XPath::NodeSet<std::string> nodes;
     
    Arabica::XPath::XPathValue<std::string> a0 = arg(0, context, executionContext);
    if(a0.type() != Arabica::XPath::NODE_SET)
      load_document(a0.asString(), nodes);
    else 
      throw Arabica::XPath::UnsupportedException("node-set arg version of document()");
    return new Arabica::XPath::NodeSetValue<std::string>(nodes);
  } // evaluate

private:
  void load_document(const std::string& location,
                     Arabica::XPath::NodeSet<std::string>& nodes) const
  {
    SAX2DOM::Parser<std::string> domParser;
    SAX::CatchErrorHandler<std::string> eh;
    domParser.setErrorHandler(eh);

    Arabica::io::URI base(baseURI_);
    Arabica::io::URI absolute(base, location);

    SAX::InputSource<std::string> is(absolute.as_string());
    domParser.parse(is);

    if(!eh.errorsReported())
        nodes.push_back(domParser.getDocument());
    else
        std::cerr << eh.errors() << std::endl;
  } // load_document

  std::string baseURI_; 
}; // DocumentFunction

// node-set key(string, object)
class KeyFunction : public Arabica::XPath::XPathFunction<std::string>
{
  typedef Arabica::XPath::XPathFunction<std::string> baseT;

public:
  KeyFunction(/* the keys, */
              const std::vector<Arabica::XPath::XPathExpression<std::string> >& args) :
    Arabica::XPath::XPathFunction<std::string>(2, 2, args) { }

  virtual Arabica::XPath::ValueType type() const { return Arabica::XPath::NODE_SET; }

  virtual Arabica::XPath::XPathValue_impl<std::string>* evaluate(const DOM::Node<std::string>& context,
                                                                 const Arabica::XPath::ExecutionContext<std::string>& executionContext) const
  {
    Arabica::XPath::XPathValue<std::string> a1 = baseT::arg(1, context, executionContext);
    if(a1.type() == Arabica::XPath::NODE_SET)
      throw Arabica::XPath::UnsupportedException("node-set arg version of document()");

    std::string keyname = argAsString(0, context, executionContext);
    std::string id = a1.asString();
    throw Arabica::XPath::UnsupportedException("key(" + keyname + ", " + id + ")");
  } // evaluate

}; // class KeyFunction

// string format-number(number, string, string?)

// node-set current()
class CurrentFunction : public Arabica::XPath::XPathFunction<std::string>
{
  typedef Arabica::XPath::XPathFunction<std::string> baseT;

public:
{'fraction_non_alphanumeric': 0.14939505523408733, 'fraction_numerical': 0.00438365772400491, 'mean_word_length': 4.422053231939164, 'pattern_counts': {'":': 0, '<': 58, '<?xml version=': 0, '>': 52, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3612485', 'n_tokens_mistral': 1820, 'n_tokens_neox': 1785, 'n_words': 307}