* Manages the lifetime of the children.\r
*/\r
std::list<XMLObject*> m_children;\r
+\r
+ /**\r
+ * Set of namespaces associated with the object.\r
+ */\r
+ std::set<Namespace> m_namespaces;\r
\r
private:\r
XMLObject* m_parent;\r
QName m_elementQname;\r
QName* m_typeQname;\r
- std::set<Namespace> m_namespaces;\r
};\r
\r
};\r
\r
void AbstractXMLObjectMarshaller::marshallInto(XMLObject& xmlObject, DOMElement* targetElement) const\r
{\r
- targetElement->setPrefix(xmlObject.getElementQName().getPrefix());\r
+ if (xmlObject.getElementQName().hasPrefix())\r
+ targetElement->setPrefix(xmlObject.getElementQName().getPrefix());\r
marshallElementType(xmlObject, targetElement);\r
marshallNamespaces(xmlObject, targetElement);\r
marshallAttributes(xmlObject, targetElement);\r
\r
const XMLCh* lookupNamespaceURI(const DOMNode* n, const XMLCh* prefix) const {\r
// Return NULL if no declaration in effect. The empty string signifies the null namespace.\r
- if (!n || n->getNodeType()!=DOMNode::ELEMENT_NODE)\r
+ if (!n || n->getNodeType()!=DOMNode::ELEMENT_NODE) {\r
+ // At the root, the default namespace is set to the null namespace.\r
+ if (!prefix || !*prefix)\r
+ return &chNull;\r
return NULL; // we're done\r
+ }\r
DOMNamedNodeMap* attributes = static_cast<const DOMElement*>(n)->getAttributes();\r
if (!attributes)\r
return lookupNamespaceURI(n->getParentNode(),prefix); // defer to parent\r
if (!XMLString::equals(attribute->getNamespaceURI(),XMLConstants::XMLNS_NS))\r
continue; // not a namespace declaration\r
// Local name should be the prefix and the value would be the URI, except for the default namespace.\r
- if (!prefix && XMLString::equals(attribute->getLocalName(),XMLConstants::XMLNS_PREFIX))\r
+ if ((!prefix || !*prefix) && XMLString::equals(attribute->getLocalName(),XMLConstants::XMLNS_PREFIX))\r
return attribute->getNodeValue();\r
else if (XMLString::equals(prefix,attribute->getLocalName()))\r
return attribute->getNodeValue();\r
#endif\r
\r
if (XT_log.isDebugEnabled()) {\r
- auto_ptr_char dname(element->getLocalName());\r
- XT_log.debug("unmarshalling DOM element %s", dname.get());\r
+ auto_ptr_char dname(element->getNodeName());\r
+ XT_log.debug("unmarshalling DOM element (%s)", dname.get());\r
}\r
\r
auto_ptr<XMLObject> xmlObject(buildXMLObject(element));\r
static const XMLCh type[]={chLatin_t, chLatin_y, chLatin_p, chLatin_e, chNull};\r
\r
if (XT_log.isDebugEnabled()) {\r
- auto_ptr_char dname(domElement->getLocalName());\r
- XT_log.debug("unmarshalling attributes for DOM element %s", dname.get());\r
+ auto_ptr_char dname(domElement->getNodeName());\r
+ XT_log.debug("unmarshalling attributes for DOM element (%s)", dname.get());\r
}\r
\r
DOMNamedNodeMap* attributes = domElement->getAttributes();\r
xmlObject.setSchemaType(xsitype.get());\r
continue;\r
}\r
- else if (nsuri) {\r
+ else if (nsuri && !XMLString::equals(nsuri,XMLConstants::XML_NS)) {\r
XT_log.debug("found namespace-qualified attribute, adding prefix to the list of namespaces on the XMLObject");\r
xmlObject.addNamespace(Namespace(nsuri, attribute->getPrefix()));\r
}\r
#endif\r
\r
if (XT_log.isDebugEnabled()) {\r
- auto_ptr_char dname(domElement->getLocalName());\r
- XT_log.debug("unmarshalling child elements of DOM element %s", dname.get());\r
+ auto_ptr_char dname(domElement->getNodeName());\r
+ XT_log.debug("unmarshalling child elements of DOM element (%s)", dname.get());\r
}\r
\r
DOMNodeList* childNodes = domElement->getChildNodes();\r
if (!unmarshaller) {\r
auto_ptr<QName> cname(XMLHelper::getNodeQName(childNode));\r
XT_log.error(\r
- "no default unmarshaller installed, found unknown child element %s", cname->toString().c_str()\r
+ "no default unmarshaller installed, found unknown child element (%s)", cname->toString().c_str()\r
);\r
throw UnmarshallingException("Unmarshaller found unknown child element, but no default unmarshaller was found.");\r
}\r
\r
if (XT_log.isDebugEnabled()) {\r
auto_ptr<QName> cname(XMLHelper::getNodeQName(childNode));\r
- XT_log.debug("unmarshalling child element %s", cname->toString().c_str());\r
+ XT_log.debug("unmarshalling child element (%s)", cname->toString().c_str());\r
}\r
\r
// Retain ownership of the unmarshalled child until it's processed by the parent.\r
\r
const XMLCh XMLConstants::XMLNS_PREFIX[] = { chLatin_x, chLatin_m, chLatin_l, chLatin_n, chLatin_s, chNull };\r
\r
+const XMLCh XMLConstants::XML_PREFIX[] = { chLatin_x, chLatin_m, chLatin_l, chNull };\r
+\r
const XMLCh XMLConstants::XSD_NS[] = // http://www.w3.org/2001/XMLSchema\r
{ chLatin_h, chLatin_t, chLatin_t, chLatin_p, chColon, chForwardSlash, chForwardSlash,\r
chLatin_w, chLatin_w, chLatin_w, chPeriod, chLatin_w, chDigit_3, chPeriod, chLatin_o, chLatin_r, chLatin_g, chForwardSlash,\r
{\r
/** XML core namespace ("http://www.w3.org/XML/1998/namespace") */\r
static const XMLCh XML_NS[]; \r
+\r
+ /** XML namespace prefix for special xml attributes ("xml") */\r
+ static const XMLCh XML_PREFIX[];\r
\r
/** XML namespace for xmlns attributes ("http://www.w3.org/2000/xmlns/") */\r
static const XMLCh XMLNS_NS[];\r
XMLObjectChildrenIterator operator+(difference_type _Off) const {
// return this + integer
- XMLObjectChildrenIterator _Tmp = *this;
- return (_Tmp += _Off);
+ return m_iter + _Off;
}
XMLObjectChildrenIterator& operator-=(difference_type _Off) {
// We override the iterator types with our constrained wrapper.
typedef XMLObjectChildrenIterator<Container> iterator;
- typedef const XMLObjectChildrenIterator<Container> const_iterator;
+ typedef XMLObjectChildrenIterator<Container> const_iterator;
/**
* Constructor to expose a typed collection of children backed by a list of a base type.
--- /dev/null
+/*\r
+ * Copyright 2001-2005 Internet2\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include "XMLObjectBaseTestCase.h"\r
+\r
+#include <fstream>\r
+#include <xercesc/util/XMLUniDefs.hpp>\r
+\r
+class ComplexXMLObjectTest : public CxxTest::TestSuite {\r
+public:\r
+ ComplexXMLObjectTest() {}\r
+\r
+ void setUp() {\r
+ XMLObjectBuilder::registerDefaultBuilder(new WildcardXMLObjectBuilder());\r
+ Marshaller::registerDefaultMarshaller(new WildcardXMLObjectMarshaller());\r
+ Unmarshaller::registerDefaultUnmarshaller(new WildcardXMLObjectUnmarshaller());\r
+ }\r
+\r
+ void tearDown() {\r
+ XMLObjectBuilder::deregisterDefaultBuilder();\r
+ Marshaller::deregisterDefaultMarshaller();\r
+ Unmarshaller::deregisterDefaultUnmarshaller();\r
+ }\r
+\r
+ void testComplexUnmarshalling() {\r
+ TS_TRACE("testComplexUnmarshalling");\r
+\r
+ string path=data_path + "ComplexXMLObject.xml";\r
+ ifstream fs(path.c_str());\r
+ DOMDocument* doc=nonvalidatingPool->parse(fs);\r
+ TS_ASSERT(doc!=NULL);\r
+\r
+ const Unmarshaller* u = Unmarshaller::getUnmarshaller(doc->getDocumentElement());\r
+ TS_ASSERT(u!=NULL);\r
+\r
+ auto_ptr<WildcardXMLObject> wcObject(dynamic_cast<WildcardXMLObject*>(u->unmarshall(doc->getDocumentElement(),true)));\r
+ TS_ASSERT(wcObject.get()!=NULL);\r
+\r
+ ListOf(XMLObject) kids=wcObject->getXMLObjects();\r
+ TSM_ASSERT_EQUALS("Number of child elements was not expected value", 2, kids.size());\r
+ \r
+\r
+ WildcardXMLObject* wc1=dynamic_cast<WildcardXMLObject*>(*(++kids.begin()));\r
+ WildcardXMLObject* wc2=dynamic_cast<WildcardXMLObject*>(*(++(wc1->getXMLObjects().begin())));\r
+ TSM_ASSERT_EQUALS("Number of child elements was not expected value", 3, wc2->getXMLObjects().size());\r
+\r
+ static const XMLCh html[] = {chLatin_h, chLatin_t, chLatin_m, chLatin_l, chNull};\r
+ static const XMLCh div[] = {chLatin_d, chLatin_i, chLatin_v, chNull};\r
+ auto_ptr_XMLCh htmlns("http://www.w3.org/1999/xhtml");\r
+ QName q(htmlns.get(),div,html);\r
+ ListOf(XMLObject)::const_iterator it=wc2->getXMLObjects().begin();\r
+ ++it; ++it;\r
+ TSM_ASSERT_EQUALS("Element QName unexpected", it->getElementQName(),q);\r
+ }\r
+\r
+};\r
endif
xmltoolingtest_h = \
- xmltoolingtest.h \
- MarshallingTest.h \
- UnknownTest.h \
- UnmarshallingTest.h
+ ComplexXMLObjectTest.h \
+ MarshallingTest.h \
+ UnknownTest.h \
+ UnmarshallingTest.h \
+ xmltoolingtest.h
noinst_HEADERS = \
- XMLObjectBaseTestCase.h
+ XMLObjectBaseTestCase.h
nodist_xmltoolingtest_SOURCES = $(xmltoolingtest_h:.h=.cpp)
}
ret=new SimpleXMLObject();
+ ret->m_namespaces=m_namespaces;
ret->setId(m_id);
ret->setValue(m_value);
xmltooling::clone(m_children, ret->m_children);
ret=new WildcardXMLObject(
getElementQName().getNamespaceURI(),getElementQName().getLocalPart(),getElementQName().getPrefix()
);
+ ret->m_namespaces=m_namespaces;
for (map<QName,XMLCh*>::const_iterator i=m_attributeMap.begin(); i!=m_attributeMap.end(); i++) {
ret->m_attributeMap[i->first]=XMLString::replicate(i->second);
}
+ ret->setTextContent(getTextContent());
xmltooling::clone(m_children, ret->m_children);
return ret;
}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<products>
+ <product id="1144"
+ xmlns="http://example.com/product-info"
+ xmlns:html="http://www.w3.org/1999/xhtml"
+ >
+ <name xml:lang="en">Python Perfect IDE</name>
+ <description>
+ Uses mind-reading technology to anticipate and accommodate
+ all user needs in Python development. Implements all
+ <html:code>from __future__ import</html:code> features though
+ the year 3000. Works well with <code>1166</code>.
+ </description>
+ </product>
+ <p:product id="1166" xmlns:p="http://example.com/product-info">
+ <p:name>XSLT Perfect IDE</p:name>
+ <p:description
+ xmlns:html="http://www.w3.org/1999/xhtml"
+ xmlns:xl="http://www.w3.org/1999/xlink"
+ >
+ <p:code>red</p:code>
+ <html:code>blue</html:code>
+ <html:div>
+ <ref xl:type="simple" xl:href="index.xml">A link</ref>
+ </html:div>
+ </p:description>
+ </p:product>
+</products>
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"\r
>\r
<File\r
+ RelativePath=".\ComplexXMLObjectTest.cpp"\r
+ >\r
+ </File>\r
+ <File\r
RelativePath=".\MarshallingTest.cpp"\r
>\r
</File>\r
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"\r
>\r
<File\r
+ RelativePath=".\ComplexXMLObjectTest.h"\r
+ >\r
+ <FileConfiguration\r
+ Name="Debug|Win32"\r
+ >\r
+ <Tool\r
+ Name="VCCustomBuildTool"\r
+ CommandLine="\perl\bin\perl.exe -w \cxxtest\cxxtestgen.pl --part --have-eh --have-std --abort-on-fail -o "$(InputName)".cpp "$(InputPath)""\r
+ Outputs=""$(InputName)".cpp"\r
+ />\r
+ </FileConfiguration>\r
+ <FileConfiguration\r
+ Name="Release|Win32"\r
+ >\r
+ <Tool\r
+ Name="VCCustomBuildTool"\r
+ CommandLine="\perl\bin\perl.exe -w \cxxtest\cxxtestgen.pl --part --have-eh --have-std --abort-on-fail -o "$(InputName)".cpp "$(InputPath)""\r
+ Outputs=""$(InputName)".cpp"\r
+ />\r
+ </FileConfiguration>\r
+ </File>\r
+ <File\r
RelativePath=".\MarshallingTest.h"\r
>\r
<FileConfiguration\r