Skip to content

Commit

Permalink
xerces-plugin: add logger, change pointer name, fix cdata deserializa…
Browse files Browse the repository at this point in the history
…tion, always use relative paths, add special chars to tests ElektraInitiative#1280
  • Loading branch information
e1528532 committed Mar 29, 2017
1 parent d34ef70 commit 7bd0fdc
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 145 deletions.
59 changes: 15 additions & 44 deletions src/plugins/xerces/deserializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <xercesc/dom/DOMNode.hpp>
#include <xercesc/parsers/XercesDOMParser.hpp>

#include <kdblogger.h>
#include <key.hpp>

XERCES_CPP_NAMESPACE_USE
Expand All @@ -34,7 +35,7 @@ using namespace kdb;
* Actual Xerces logic
*/

static xerces_unique_ptr<DOMDocument> doc2dom (std::string const & src)
static XercesPtr<DOMDocument> doc2dom (std::string const & src)
{
XercesDOMParser parser;
parser.setValidationScheme (XercesDOMParser::Val_Auto);
Expand All @@ -43,7 +44,7 @@ static xerces_unique_ptr<DOMDocument> doc2dom (std::string const & src)
parser.setCreateEntityReferenceNodes (false);

parser.parse (asXMLCh (src));
return xerces_unique_ptr<DOMDocument> (parser.adoptDocument ());
return XercesPtr<DOMDocument> (parser.adoptDocument ());
}

static string getElementText (DOMNode const * parent)
Expand All @@ -52,7 +53,7 @@ static string getElementText (DOMNode const * parent)

for (auto child = parent->getFirstChild (); child != NULL; child = child->getNextSibling ())
{
if (DOMNode::TEXT_NODE == child->getNodeType ())
if (DOMNode::TEXT_NODE == child->getNodeType () || DOMNode::CDATA_SECTION_NODE == child->getNodeType ())
{
DOMText * data = dynamic_cast<DOMText *> (child);
if (!data->getIsElementContentWhitespace ()) str += toStr (data->getData ());
Expand All @@ -73,7 +74,7 @@ static void dom2keyset (DOMNode const * n, Key const & parent, KeySet & ks)
if (n->getNodeType () == DOMNode::ELEMENT_NODE)
{
string keyName = toStr (n->getNodeName ());
cout << "Encountered Element : " << keyName << endl;
ELEKTRA_LOG_DEBUG ("Encountered Element: %s", keyName.c_str ());
current.addBaseName (keyName);

string text = getElementText (n);
Expand All @@ -84,26 +85,27 @@ static void dom2keyset (DOMNode const * n, Key const & parent, KeySet & ks)
// TODO we've encountered an invalid namespace or keyname, ignore, fail, ?
}

cout << "new parent is " << current.getFullName () << " with value " << current.get<string> () << endl;
ELEKTRA_LOG_DEBUG ("new parent is %s with value %s", current.getFullName ().c_str (),
current.get<string> ().c_str ());

if (n->hasAttributes ())
{
// get all the attributes of the node
DOMNamedNodeMap * pAttributes = n->getAttributes ();
const XMLSize_t nSize = pAttributes->getLength ();
cout << "\tAttributes" << endl;
ELEKTRA_LOG_DEBUG ("\tAttributes");
for (XMLSize_t i = 0; i < nSize; ++i)
{
DOMAttr * pAttributeNode = dynamic_cast<DOMAttr *> (pAttributes->item (i));
cout << "\t" << toStr (pAttributeNode->getName ()) << "=";
cout << toStr (pAttributeNode->getValue ()) << endl;
ELEKTRA_LOG_DEBUG ("\t%s=%s", asCStr (pAttributeNode->getName ()),
asCStr (pAttributeNode->getValue ()));
current.setMeta (toStr (pAttributeNode->getName ()), toStr (pAttributeNode->getValue ()));
}
}
// Only add keys with a value, attributes or leafs
if (n->hasAttributes () || !text.empty () || !n->getFirstChild ())
{
cout << "adding " << current.getFullName () << endl;
ELEKTRA_LOG_DEBUG ("adding %s", current.getFullName ().c_str ());
ks.append (current);
}
}
Expand All @@ -112,41 +114,10 @@ static void dom2keyset (DOMNode const * n, Key const & parent, KeySet & ks)
}
}

void dom2keyset (DOMDocument const & doc, Key const & parent, KeySet & ks)
{
// root namespace element
DOMElement * root = doc.getDocumentElement ();

if (root)
{
if (!parent.isValid ())
{
// the namespace elements for absolute exports
for (auto ns = root->getFirstChild (); ns != nullptr; ns = ns->getNextSibling ())
{
string keyName = toStr (ns->getNodeName ());
if (keyName == "cascading") keyName = "/";
// the actual content nodes
for (auto child = ns->getFirstChild (); child != nullptr; child = child->getNextSibling ())
{
dom2keyset (child, Key (keyName), ks);
}
}
}
else
{
// Otherwise we can begin right away and don't have to parse namespaces
for (auto child = root->getFirstChild (); child != nullptr; child = child->getNextSibling ())
{
dom2keyset (child, parent, ks);
}
}
}
}

void deserialize (Key const & parentKey, KeySet & ks)
{
cout << "deserialize with parent " << parentKey.get<string> () << flush << endl;
ELEKTRA_LOG_DEBUG ("deserializing relative to %s from file %s", parentKey.getFullName ().c_str (),
parentKey.get<string> ().c_str ());
auto document = doc2dom (parentKey.get<string> ());
if (document) dom2keyset (*document, parentKey, ks);
}
if (document) dom2keyset (document->getDocumentElement (), parentKey, ks);
}
11 changes: 6 additions & 5 deletions src/plugins/xerces/serializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/util/XMLString.hpp>

#include <kdblogger.h>
#include <key.hpp>

XERCES_CPP_NAMESPACE_USE
Expand Down Expand Up @@ -74,7 +75,7 @@ static void appendKey (DOMDocument & doc, Key const & parentKey, Key const & key
itKey.rewindMeta ();
while (Key const & meta = itKey.nextMeta ())
{
cout << "setting element " << meta.getName () << " to " << meta.get<string> () << flush << endl;
ELEKTRA_LOG_DEBUG ("setting element %s to %s", meta.getName ().c_str (), meta.get<string> ().c_str ());
elem->setAttribute (asXMLCh (meta.getName ()), asXMLCh (meta.get<string> ()));
}

Expand All @@ -94,22 +95,22 @@ void serialize (Key const & parentKey, KeySet const & ks)
DOMImplementation * impl = DOMImplementationRegistry::getDOMImplementation (asXMLCh ("Core"));
if (impl != NULL)
{
xerces_unique_ptr<DOMDocument> document (impl->createDocument (0, asXMLCh ("namespace"), 0));
XercesPtr<DOMDocument> document (impl->createDocument (0, asXMLCh ("namespace"), 0));
ks2dom (*document, parentKey, ks);

DOMImplementationLS * implLS = dynamic_cast<DOMImplementationLS *> (impl->getImplementation ());

xerces_unique_ptr<DOMLSSerializer> serializer (implLS->createLSSerializer ());
XercesPtr<DOMLSSerializer> serializer (implLS->createLSSerializer ());
DOMConfiguration * serializerConfig = serializer->getDomConfig ();
if (serializerConfig->canSetParameter (XMLUni::fgDOMWRTFormatPrettyPrint, true))
serializerConfig->setParameter (XMLUni::fgDOMWRTFormatPrettyPrint, true);

LocalFileFormatTarget targetFile (asXMLCh (parentKey.get<string> ()));
xerces_unique_ptr<DOMLSOutput> output (implLS->createLSOutput ());
XercesPtr<DOMLSOutput> output (implLS->createLSOutput ());
output->setByteStream (&targetFile);

serializer->write (document.get (), output.get ());
}
else
throw XercesPluginException ("DOMImplementation not available");
}
}
6 changes: 0 additions & 6 deletions src/plugins/xerces/testdata/relative.xml

This file was deleted.

36 changes: 9 additions & 27 deletions src/plugins/xerces/testdata/simple.xml
Original file line number Diff line number Diff line change
@@ -1,28 +1,10 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<namespace>
<cascading>
<sw>
<elektra>
<tests>
<xerces>
<!-- this is an attribute -->
<fizz buzz="fizzBuzz" />
value of xerces
</xerces>
</tests>
</elektra>
</sw>
</cascading>
<user>
<sw>
<elektra>
<tests>
<xerces>
<userKey user="key">withValue</userKey>
</xerces>
</tests>
<!-- comments are ignored -->
</elektra>
</sw>
</user>
</namespace>
<xerces>
<!-- this is an attribute -->
<fizz buzz="fizzBuzz" />
value of xerces<!-- Comment inside text -->
<userKey user="key">withValue</userKey>
<!-- those need escaping: " ' < > & -->
<späciöl_-keüs1 attr='"' attr2="$%(){}``äüö²[/\'>&quot;&lt;&apos;&amp;">>"&amp;&lt;'</späciöl_-keüs1>
<cdata more-s_päcials="1 &amp; 2 are &lt; &#51; &#x0A;"><![CDATA[this is some cdata text "'<>&ä "]]></cdata>
</xerces>
98 changes: 41 additions & 57 deletions src/plugins/xerces/testmod_xerces.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ static void test_simple_read ()
{
printf ("test simple read\n");

Key * parentKey = keyNew ("", KEY_VALUE, srcdir_file ("testdata/simple.xml"), KEY_END);
Key * parentKey = keyNew ("/sw/elektra/tests", KEY_VALUE, srcdir_file ("testdata/simple.xml"), KEY_END);
KeySet * conf = ksNew (0, KS_END);
PLUGIN_OPEN ("xerces");

Expand Down Expand Up @@ -72,10 +72,10 @@ static void test_simple_read ()
}
}

succeed_if (current = ksLookupByName (ks, "user/sw/elektra/tests/xerces/userKey", 0), "userKey key not found");
succeed_if (current = ksLookupByName (ks, "/sw/elektra/tests/xerces/userKey", 0), "userKey key not found");
if (current)
{
succeed_if (strcmp (keyName (current), "user/sw/elektra/tests/xerces/userKey") == 0, "wrong name");
succeed_if (strcmp (keyName (current), "/sw/elektra/tests/xerces/userKey") == 0, "wrong name");
succeed_if (strcmp (keyValue (current), "withValue") == 0, "value not correct");

const Key * meta;
Expand All @@ -87,6 +87,43 @@ static void test_simple_read ()
}
}

succeed_if (current = ksLookupByName (ks, "/sw/elektra/tests/xerces/späciöl_-keüs1", 0), "späciöl_-keüs1 key not found");
if (current)
{
succeed_if (strcmp (keyName (current), "/sw/elektra/tests/xerces/späciöl_-keüs1") == 0, "wrong name");
succeed_if (strcmp (keyValue (current), ">\"&<'") == 0, "value not correct");

const Key * meta;
succeed_if (meta = keyGetMeta (current, "attr"), "no metadata exists");
if (meta)
{
succeed_if (strcmp (keyName (meta), "attr") == 0, "wrong metadata name");
succeed_if (strcmp (keyValue (meta), "\"") == 0, "wrong metadata value");
}
succeed_if (meta = keyGetMeta (current, "attr2"), "no metadata exists");
if (meta)
{
succeed_if (strcmp (keyName (meta), "attr2") == 0, "wrong metadata name");
succeed_if (strcmp (keyValue (meta), "$%(){}``äüö²[/\\'>\"<'&") == 0, "wrong metadata value");
}
}

succeed_if (current = ksLookupByName (ks, "/sw/elektra/tests/xerces/cdata", 0), "cdata key not found");
if (current)
{
succeed_if (strcmp (keyName (current), "/sw/elektra/tests/xerces/cdata") == 0, "wrong name");

succeed_if (strcmp (keyValue (current), "this is some cdata text \"'<>&ä \"") == 0, "value not correct");

const Key * meta;
succeed_if (meta = keyGetMeta (current, "more-s_päcials"), "no metadata exists");
if (meta)
{
succeed_if (strcmp (keyName (meta), "more-s_päcials") == 0, "wrong metadata name");
succeed_if (strcmp (keyValue (meta), "1 & 2 are < 3 \n") == 0, "wrong metadata value");
}
}

keyDel (parentKey);
ksDel (ks);
PLUGIN_CLOSE ();
Expand All @@ -100,7 +137,7 @@ static void test_simple_write ()
printf ("test simple write\n");
fflush (stdout);

Key * parentKey = keyNew ("", KEY_VALUE, srcdir_file ("testdata/simple-gen.xml"), KEY_END);
Key * parentKey = keyNew ("/sw/elektra/tests/xerces", KEY_VALUE, srcdir_file ("testdata/simple-gen.xml"), KEY_END);
KeySet * conf = ksNew (0, KS_END);
PLUGIN_OPEN ("xerces");

Expand All @@ -110,7 +147,6 @@ static void test_simple_write ()
keyNew ("user/sw/elektra/tests/xerces/userKey", KEY_VALUE, "withValue", KEY_END), keyWithMeta, KS_END);

succeed_if (plugin->kdbSet (plugin, ks, parentKey) == 1, "call to kdbSet was not successful");
// TODO somehow this corrupts the parentKey????
// As compare_files does not take different formatting into account, compare using deserialization again
KeySet * result = ksNew (2, KS_END);
succeed_if (plugin->kdbGet (plugin, result, parentKey) == 1, "call to kdbGet was not successful");
Expand All @@ -127,57 +163,6 @@ static void test_simple_write ()
fflush (stdout);
}

static void test_relative ()
{
printf ("test relative read\n");

// TODO decide if the im/export should take /xerces/ into account too (it acts as root element in the xml) or not
Key * parentKey = keyNew ("/sw/elektra/tests/xerces/", KEY_VALUE, srcdir_file ("testdata/relative.xml"), KEY_END);
KeySet * conf = ksNew (0, KS_END);
PLUGIN_OPEN ("xerces");

KeySet * ks = ksNew (0, KS_END);
Key * current;

succeed_if (plugin->kdbGet (plugin, ks, parentKey) == 1, "call to kdbGet was not successful");

succeed_if (current = ksLookupByName (ks, "/sw/elektra/tests/xerces/fizz", 0), "fizz key not found");
if (current)
{
succeed_if (strcmp (keyName (current), "/sw/elektra/tests/xerces/fizz") == 0, "wrong name");

const Key * meta;
succeed_if (meta = keyGetMeta (current, "buzz"), "no metadata exists");
if (meta)
{
succeed_if (strcmp (keyName (meta), "buzz") == 0, "wrong metadata name");
succeed_if (strcmp (keyValue (meta), "fizzBuzz") == 0, "wrong metadata value");
}
}

succeed_if (current = ksLookupByName (ks, "/sw/elektra/tests/xerces/userKey", 0), "userKey key not found");
if (current)
{
succeed_if (strcmp (keyName (current), "/sw/elektra/tests/xerces/userKey") == 0, "wrong name");
succeed_if (strcmp (keyValue (current), "withValue") == 0, "value not correct");

const Key * meta;
succeed_if (meta = keyGetMeta (current, "user"), "no metadata exists");
if (meta)
{
succeed_if (strcmp (keyName (meta), "user") == 0, "wrong metadata name");
succeed_if (strcmp (keyValue (meta), "key") == 0, "wrong metadata value");
}
}

keyDel (parentKey);
ksDel (ks);
PLUGIN_CLOSE ();

printf ("test relative finished\n");
fflush (stdout);
}

int main (int argc, char ** argv)
{
printf ("XERCES TESTS\n");
Expand All @@ -188,7 +173,6 @@ int main (int argc, char ** argv)
test_basics ();
test_simple_read ();
test_simple_write ();
test_relative ();

printf ("\ntestmod_xerces RESULTS: %d test(s) done. %d error(s).\n", nbTest, nbError);

Expand Down
10 changes: 5 additions & 5 deletions src/plugins/xerces/util.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,16 @@ struct XercesDeleter<char>
};

template <typename T>
using xerces_unique_ptr = std::unique_ptr<T, XercesDeleter<T>>;
using XercesPtr = std::unique_ptr<T, XercesDeleter<T>>;

inline xerces_unique_ptr<XMLCh> toXMLCh (std::string const & str)
inline XercesPtr<XMLCh> toXMLCh (std::string const & str)
{
return xerces_unique_ptr<XMLCh> (XERCES_CPP_NAMESPACE::XMLString::transcode (str.c_str ()));
return XercesPtr<XMLCh> (XERCES_CPP_NAMESPACE::XMLString::transcode (str.c_str ()));
}

inline xerces_unique_ptr<char> toCStr (XMLCh const * xmlCh)
inline XercesPtr<char> toCStr (XMLCh const * xmlCh)
{
return xerces_unique_ptr<char> (XERCES_CPP_NAMESPACE::XMLString::transcode (xmlCh));
return XercesPtr<char> (XERCES_CPP_NAMESPACE::XMLString::transcode (xmlCh));
}

inline std::string toStr (XMLCh const * xmlCh)
Expand Down
1 change: 0 additions & 1 deletion src/plugins/xerces/xerces.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,4 +161,3 @@ Plugin * ELEKTRA_PLUGIN_EXPORT (xerces)
ELEKTRA_PLUGIN_ERROR, &elektraXercesError,
ELEKTRA_PLUGIN_END);
}

0 comments on commit 7bd0fdc

Please sign in to comment.