|
#include <iostream>
|
|
#include <sys/sysinfo.h>
|
|
#include "SaxonProcessor.h"
|
|
#include "XdmNode.h"
|
|
|
|
using namespace std;
|
|
|
|
XdmNode *getElement(XdmNode *, const std::string, SaxonProcessor*);
|
|
XdmNode *getRoot(XdmNode *);
|
|
void printElement(XdmNode *);
|
|
void printChildren(XdmNode *);
|
|
|
|
int main(int argc, char* argv[])
|
|
{
|
|
cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
|
|
|
|
std::string xml =
|
|
"<root root-attribute=\"root-attribute-data\">\n"
|
|
" <first-child first-child-attribute=\"first-child-attribute-data\">\n"
|
|
" first-child-data\n"
|
|
" </first-child>\n"
|
|
" <second-child second-child-attribute=\"second-child-attribute-data\">\n"
|
|
" second-child-data\n"
|
|
" </second-child>\n"
|
|
" <third-child third-child-attribute=\"third-child-attribute-data\">\n"
|
|
" third-child-data\n"
|
|
" </third-child>\n"
|
|
"</root>\n";
|
|
|
|
|
|
printf("XML: %s\n", xml.c_str());
|
|
|
|
SaxonProcessor * processor = new SaxonProcessor(true);
|
|
processor->setConfigurationProperty("http://saxon.sf.net/feature/licenseFileLocation",
|
|
"/usr/lib/saxon-j/saxon-license.lic");
|
|
processor->setConfigurationProperty("http://saxon.sf.net/feature/multipleSchemaImports", "on");
|
|
processor->setConfigurationProperty("xsdversion", "1.0");
|
|
|
|
try
|
|
{
|
|
// parser the XML
|
|
XdmNode *document = processor->parseXmlFromString(xml.c_str());
|
|
|
|
if (document == nullptr)
|
|
{
|
|
fprintf(stderr, "Parsing of XML failed\n");
|
|
return -1;
|
|
}
|
|
|
|
// get the root element
|
|
std::string rootElementName = "root";
|
|
|
|
//
|
|
/**
|
|
* ISSUE #2:
|
|
* Regardless of whether you use getElement or getRoot() to get the
|
|
* root element, deleting the node at the end of the program gives a
|
|
* 'double free detected in tcache 2' error
|
|
*/
|
|
#if 1
|
|
XdmNode *root = getElement(document, rootElementName.c_str(), processor);
|
|
#else
|
|
XdmNode *root = getRoot(document);
|
|
#endif
|
|
|
|
if (root == nullptr)
|
|
{
|
|
fprintf(stderr, "Could not get root element\n");
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* ISSUE #4:
|
|
* If you make a copy of the XdmNode in getRoot(),
|
|
* this returns NULL
|
|
*/
|
|
// get the root element's value
|
|
const char *rootElementValue = root->getStringValue();
|
|
|
|
if (rootElementValue != nullptr)
|
|
{
|
|
printf("Root element: Name=%s, Value=%s\n", rootElementName.c_str(),
|
|
rootElementValue);
|
|
|
|
operator delete((char *)rootElementValue);
|
|
}
|
|
|
|
// // print the root element
|
|
// printElement(root);
|
|
|
|
// get the root's attribute value
|
|
std::string rootAttributeName = "root-attribute";
|
|
|
|
/**
|
|
* ISSUE #4:
|
|
* If you make a copy of the XdmNode in getRoot(),
|
|
* this returns throws a ava.lang.NullPointerException
|
|
* at net.sf.saxon.option.cpp.XdmUtils.getAttributeValue(XdmUtils.java:1262)
|
|
*/
|
|
const char *rootAttributeValue = root->getAttributeValue(rootAttributeName.c_str());
|
|
|
|
if (rootAttributeValue != nullptr)
|
|
{
|
|
printf("Root attribute: Name=%s, Value=%s\n", rootAttributeName.c_str(),
|
|
rootAttributeValue);
|
|
|
|
#if 0
|
|
/**
|
|
* ISSUE #1:
|
|
* This gives 'double free or corruption' error
|
|
*/
|
|
operator delete((char *)rootAttributeValue);
|
|
#endif
|
|
}
|
|
|
|
printChildren(root);
|
|
#if 0
|
|
/**
|
|
* ISSUE #3:
|
|
* A second call to printChildren gives a SEG FAULT (SIGSEGV)
|
|
*/
|
|
printChildren(root);
|
|
#endif
|
|
|
|
#if 1
|
|
/**
|
|
* ISSUE #2:
|
|
* This gives double free detected in tcache 2 regardless of
|
|
* whether you use getRoot() or getElement() to get the root node
|
|
*/
|
|
delete root;
|
|
#endif
|
|
delete document;
|
|
}
|
|
catch(SaxonApiException &e)
|
|
{
|
|
cout<<"Exception parsing XML: "<<e.what()<<endl;
|
|
}
|
|
|
|
delete processor;
|
|
SaxonProcessor::release();
|
|
|
|
return 0;
|
|
}
|
|
|
|
XdmNode *getRoot(XdmNode *document)
|
|
{
|
|
XdmNode *root = nullptr;
|
|
|
|
XdmNode **children = document->getChildren();
|
|
|
|
if (children != nullptr)
|
|
{
|
|
int childCount = document->getChildCount();
|
|
bool found = false;
|
|
for (int i=0; i<childCount; i++)
|
|
{
|
|
XdmNode *child = children[i];
|
|
if (child != nullptr)
|
|
{
|
|
if (found)
|
|
{
|
|
delete child;
|
|
}
|
|
else if (child->getNodeKind() == XDM_NODE_KIND::ELEMENT)
|
|
{
|
|
#if 0
|
|
/**
|
|
* ISSUE #4:
|
|
* If you make a copy of the node, calls to it return nullptrs
|
|
* or throw java NullPointerExceptions.
|
|
*/
|
|
// Make a copy so we can pass it around
|
|
root = new XdmNode(*child);
|
|
delete child;
|
|
#else
|
|
root = child;
|
|
#endif
|
|
found = true;
|
|
}
|
|
}
|
|
}
|
|
delete [] children;
|
|
}
|
|
|
|
|
|
return root;
|
|
}
|
|
|
|
XdmNode *getElement(XdmNode *node, const std::string name, SaxonProcessor* processor)
|
|
{
|
|
XdmNode *element = nullptr;
|
|
|
|
XPathProcessor *xpath = processor->newXPathProcessor();
|
|
xpath->setLanguageVersion("3.1");
|
|
|
|
std::string xpathExpression = "//" + name;
|
|
|
|
try
|
|
{
|
|
xpath->setContextItem((XdmItem *)node);
|
|
|
|
XdmValue *elements = xpath->evaluate(xpathExpression.c_str());
|
|
printf("XPath expression: %s, # of values returned: %d\n",
|
|
xpathExpression.c_str(), elements->size());
|
|
|
|
if (elements->size())
|
|
{
|
|
XdmItem * item = elements->itemAt(0);
|
|
|
|
if ((item != nullptr) && (item->getType() == XDM_TYPE::XDM_NODE))
|
|
{
|
|
/**
|
|
* ISSUE #2:
|
|
* Regardless of whether or you make a copy of the XdmItem
|
|
* you get a 'double free detected in tcache 2' error when
|
|
* you delete it.
|
|
*/
|
|
#if 1
|
|
// Make a copy so we can pass it around
|
|
element = new XdmNode(*((XdmNode *)item));
|
|
#else
|
|
element = (XdmNode *)item;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
delete elements;
|
|
}
|
|
catch(SaxonApiException &e)
|
|
{
|
|
printf("Exception evaluating xpath expression %s: %s\n",
|
|
xpathExpression.c_str(), e.what());
|
|
}
|
|
|
|
delete xpath;
|
|
|
|
return element;
|
|
}
|
|
|
|
void printElement(XdmNode * node)
|
|
{
|
|
printf("Element:\n");
|
|
printf(" Name: %s\n", node->getLocalName());
|
|
printf(" # of Children: %d\n", node->getChildCount());
|
|
|
|
int attributeCount = node->getAttributeCount();
|
|
printf(" # of Attributes: %d\n", attributeCount);
|
|
printf("\n");
|
|
}
|
|
|
|
|
|
void printChildren(XdmNode *node)
|
|
{
|
|
XdmNode **children = node->getChildren();
|
|
if (children != nullptr)
|
|
{
|
|
int childCount = node->getChildCount();
|
|
for (int i=0; i<childCount; i++)
|
|
{
|
|
XdmNode *child = children[i];
|
|
if (child != nullptr)
|
|
{
|
|
if (child->getNodeKind() == XDM_NODE_KIND::ELEMENT)
|
|
{
|
|
printElement(child);
|
|
}
|
|
|
|
/**
|
|
* ISSUE #3:
|
|
* If you make a second call to printChildren(),
|
|
* this gives SEG FAULT (SIGSEGV)
|
|
*/
|
|
delete child;
|
|
}
|
|
}
|
|
|
|
delete [] children;
|
|
}
|
|
}
|