From: Scott Cantor Date: Thu, 23 Mar 2006 04:26:51 +0000 (+0000) Subject: Handle variant element names, merge in wildcard class, add test cases. X-Git-Tag: 1.0-alpha1~290 X-Git-Url: http://www.project-moonshot.org/gitweb/?p=shibboleth%2Fcpp-xmltooling.git;a=commitdiff_plain;h=9736bf8a914e9b64ad37269829f59370f15fbcbb Handle variant element names, merge in wildcard class, add test cases. --- diff --git a/xmltooling/AbstractXMLObject.h b/xmltooling/AbstractXMLObject.h index e72f3eb..d5ebc71 100644 --- a/xmltooling/AbstractXMLObject.h +++ b/xmltooling/AbstractXMLObject.h @@ -52,6 +52,7 @@ namespace xmltooling { */ void setElementNamespacePrefix(const XMLCh* prefix) { m_elementQname.setPrefix(prefix); + addNamespace(Namespace(m_elementQname.getNamespaceURI(),prefix)); } /** diff --git a/xmltooling/Makefile.am b/xmltooling/Makefile.am index e90aca3..bd9a7fd 100644 --- a/xmltooling/Makefile.am +++ b/xmltooling/Makefile.am @@ -32,6 +32,10 @@ libxmltoolinginclude_HEADERS = \ XMLObjectBuilder.h \ XMLToolingConfig.h +implinclude_HEADERS = \ + impl/AnyElement.h \ + impl/UnknownElement.h + ioinclude_HEADERS = \ io/AbstractXMLObjectUnmarshaller.h \ @@ -52,7 +56,6 @@ valinclude_HEADERS = \ noinst_HEADERS = \ internal.h \ - impl/UnknownElement.h \ signature/impl/XMLSecSignature.h if BUILD_XMLSEC @@ -72,6 +75,7 @@ libxmltooling_la_SOURCES = \ unicode.cpp \ XMLObjectBuilder.cpp \ XMLToolingConfig.cpp \ + impl/AnyElement.cpp \ impl/UnknownElement.cpp \ io/AbstractXMLObjectMarshaller.cpp \ io/AbstractXMLObjectUnmarshaller.cpp \ diff --git a/xmltooling/XMLObjectBuilder.h b/xmltooling/XMLObjectBuilder.h index 4426401..0b05e46 100644 --- a/xmltooling/XMLObjectBuilder.h +++ b/xmltooling/XMLObjectBuilder.h @@ -1,200 +1,224 @@ -/* - * Copyright 2001-2006 Internet2 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file XMLObjectBuilder.h - * - * Factory interface for XMLObjects - */ - -#if !defined(__xmltooling_xmlobjbuilder_h__) -#define __xmltooling_xmlobjbuilder_h__ - -#include -#include -#include - -#if defined (_MSC_VER) - #pragma warning( push ) - #pragma warning( disable : 4250 4251 ) -#endif - -namespace xmltooling { - - /** - * A factory interface for obtaining XMLObjects. - * Subclasses MAY supply additional factory methods. - */ - class XMLTOOL_API XMLObjectBuilder - { - MAKE_NONCOPYABLE(XMLObjectBuilder); - public: - virtual ~XMLObjectBuilder() {} - - /** - * Creates an empty XMLObject. - * - * @return the empty XMLObject - */ - virtual XMLObject* buildObject() const=0; - - /** - * Creates an unmarshalled XMLObject from a DOM Element. - * - * @param element the unmarshalling source - * @param bindDocument true iff the XMLObject should take ownership of the DOM Document - * @return the unmarshalled XMLObject - */ - virtual XMLObject* buildFromElement(DOMElement* element, bool bindDocument=false) const { - std::auto_ptr ret(buildObject()); - ret->unmarshall(element,bindDocument); - return ret.release(); - } - - /** - * Creates an unmarshalled XMLObject from the root of a DOM Document. - * - * @param doc the unmarshalling source - * @param bindDocument true iff the XMLObject should take ownership of the DOM Document - * @return the unmarshalled XMLObject - */ - virtual XMLObject* buildFromDocument(DOMDocument* doc, bool bindDocument=true) const { - return buildFromElement(doc->getDocumentElement(),bindDocument); - } - - /** - * Creates an empty XMLObject using the default build method, if a builder can be found. - * - * @param key the key used to locate a builder - * @return the empty object or NULL if no builder is available - */ - static XMLObject* buildOne(const QName& key) { - const XMLObjectBuilder* b=getBuilder(key); - if (b) - return b->buildObject(); - b=getDefaultBuilder(); - return b ? b->buildObject() : NULL; - } - - /** - * Creates an unmarshalled XMLObject using the default build method, if a builder can be found. - * - * @param element the unmarshalling source - * @param bindDocument true iff the new XMLObject should take ownership of the DOM Document - * @return the unmarshalled object or NULL if no builder is available - */ - static XMLObject* buildOneFromElement(DOMElement* element, bool bindDocument=false) { - const XMLObjectBuilder* b=getBuilder(element); - return b ? b->buildFromElement(element,bindDocument) : NULL; - } - - /** - * Retrieves an XMLObjectBuilder using the key it was registered with. - * - * @param key the key used to register the builder - * @return the builder or NULL - */ - static const XMLObjectBuilder* getBuilder(const QName& key) { - std::map::const_iterator i=m_map.find(key); - return (i==m_map.end()) ? NULL : i->second; - } - - /** - * Retrieves an XMLObjectBuilder for a given DOM element. - * If no match is found, the default builder is returned, if any. - * - * @param element the element for which to locate a builder - * @return the builder or NULL - */ - static const XMLObjectBuilder* getBuilder(const DOMElement* element); - - /** - * Retrieves the default XMLObjectBuilder for DOM elements - * - * @return the default builder or NULL - */ - static const XMLObjectBuilder* getDefaultBuilder() { - return m_default; - } - - /** - * Gets an immutable list of all the builders currently registered. - * - * @return list of all the builders currently registered - */ - static const std::map& getBuilders() { - return m_map; - } - - /** - * Registers a new builder for the given key. - * - * @param builderKey the key used to retrieve this builder later - * @param builder the builder - */ - static void registerBuilder(const QName& builderKey, XMLObjectBuilder* builder) { - deregisterBuilder(builderKey); - m_map[builderKey]=builder; - } - - /** - * Registers a default builder - * - * @param builder the default builder - */ - static void registerDefaultBuilder(XMLObjectBuilder* builder) { - deregisterDefaultBuilder(); - m_default=builder; - } - - /** - * Deregisters a builder. - * - * @param builderKey the key for the builder to be deregistered - */ - static void deregisterBuilder(const QName& builderKey) { - delete getBuilder(builderKey); - m_map.erase(builderKey); - } - - /** - * Deregisters default builder. - */ - static void deregisterDefaultBuilder() { - delete m_default; - m_default=NULL; - } - - /** - * Unregisters and destroys all registered builders. - */ - static void destroyBuilders(); - - protected: - XMLObjectBuilder() {} - - private: - static std::map m_map; - static XMLObjectBuilder* m_default; - }; - -}; - -#if defined (_MSC_VER) - #pragma warning( pop ) -#endif - -#endif /* __xmltooling_xmlobjbuilder_h__ */ +/* + * Copyright 2001-2006 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file XMLObjectBuilder.h + * + * Factory interface for XMLObjects + */ + +#if !defined(__xmltooling_xmlobjbuilder_h__) +#define __xmltooling_xmlobjbuilder_h__ + +#include +#include +#include + +#if defined (_MSC_VER) + #pragma warning( push ) + #pragma warning( disable : 4250 4251 ) +#endif + +namespace xmltooling { + + /** + * A factory interface for obtaining XMLObjects. + * Subclasses MAY supply additional factory methods. + */ + class XMLTOOL_API XMLObjectBuilder + { + MAKE_NONCOPYABLE(XMLObjectBuilder); + public: + virtual ~XMLObjectBuilder() {} + + /** + * Creates an empty XMLObject with a particular element name. + * + * @param namespaceURI namespace URI for element + * @param elementLocalName local name of element + * @param namespacePrefix prefix of element name + * @return the empty XMLObject + */ + virtual XMLObject* buildObject( + const XMLCh* namespaceURI, const XMLCh* elementLocalName, const XMLCh* namespacePrefix=NULL + ) const=0; + + /** + * Creates an empty XMLObject with a defaulted element name. + * + * @return the empty XMLObject + */ + virtual XMLObject* buildObject() const { + return buildObject(NULL,NULL,NULL); + } + + /** + * Creates an empty XMLObject with a particular element name. + * + * @param q QName of element for object + * @return the empty XMLObject + */ + virtual XMLObject* buildObject(const QName& q) const { + return buildObject(q.getNamespaceURI(),q.getLocalPart(),q.getPrefix()); + } + + /** + * Creates an unmarshalled XMLObject from a DOM Element. + * + * @param element the unmarshalling source + * @param bindDocument true iff the XMLObject should take ownership of the DOM Document + * @return the unmarshalled XMLObject + */ + virtual XMLObject* buildFromElement(DOMElement* element, bool bindDocument=false) const { + std::auto_ptr ret(buildObject(element->getNamespaceURI(),element->getLocalName(),element->getPrefix())); + ret->unmarshall(element,bindDocument); + return ret.release(); + } + + /** + * Creates an unmarshalled XMLObject from the root of a DOM Document. + * + * @param doc the unmarshalling source + * @param bindDocument true iff the XMLObject should take ownership of the DOM Document + * @return the unmarshalled XMLObject + */ + virtual XMLObject* buildFromDocument(DOMDocument* doc, bool bindDocument=true) const { + return buildFromElement(doc->getDocumentElement(),bindDocument); + } + + /** + * Creates an empty XMLObject using the default build method, if a builder can be found. + * + * @param key the key used to locate a builder + * @return the empty object or NULL if no builder is available + */ + static XMLObject* buildOne(const QName& key) { + const XMLObjectBuilder* b=getBuilder(key); + if (b) + return b->buildObject(); + b=getDefaultBuilder(); + return b ? b->buildObject() : NULL; + } + + /** + * Creates an unmarshalled XMLObject using the default build method, if a builder can be found. + * + * @param element the unmarshalling source + * @param bindDocument true iff the new XMLObject should take ownership of the DOM Document + * @return the unmarshalled object or NULL if no builder is available + */ + static XMLObject* buildOneFromElement(DOMElement* element, bool bindDocument=false) { + const XMLObjectBuilder* b=getBuilder(element); + return b ? b->buildFromElement(element,bindDocument) : NULL; + } + + /** + * Retrieves an XMLObjectBuilder using the key it was registered with. + * + * @param key the key used to register the builder + * @return the builder or NULL + */ + static const XMLObjectBuilder* getBuilder(const QName& key) { + std::map::const_iterator i=m_map.find(key); + return (i==m_map.end()) ? NULL : i->second; + } + + /** + * Retrieves an XMLObjectBuilder for a given DOM element. + * If no match is found, the default builder is returned, if any. + * + * @param element the element for which to locate a builder + * @return the builder or NULL + */ + static const XMLObjectBuilder* getBuilder(const DOMElement* element); + + /** + * Retrieves the default XMLObjectBuilder for DOM elements + * + * @return the default builder or NULL + */ + static const XMLObjectBuilder* getDefaultBuilder() { + return m_default; + } + + /** + * Gets an immutable list of all the builders currently registered. + * + * @return list of all the builders currently registered + */ + static const std::map& getBuilders() { + return m_map; + } + + /** + * Registers a new builder for the given key. + * + * @param builderKey the key used to retrieve this builder later + * @param builder the builder + */ + static void registerBuilder(const QName& builderKey, XMLObjectBuilder* builder) { + deregisterBuilder(builderKey); + m_map[builderKey]=builder; + } + + /** + * Registers a default builder + * + * @param builder the default builder + */ + static void registerDefaultBuilder(XMLObjectBuilder* builder) { + deregisterDefaultBuilder(); + m_default=builder; + } + + /** + * Deregisters a builder. + * + * @param builderKey the key for the builder to be deregistered + */ + static void deregisterBuilder(const QName& builderKey) { + delete getBuilder(builderKey); + m_map.erase(builderKey); + } + + /** + * Deregisters default builder. + */ + static void deregisterDefaultBuilder() { + delete m_default; + m_default=NULL; + } + + /** + * Unregisters and destroys all registered builders. + */ + static void destroyBuilders(); + + protected: + XMLObjectBuilder() {} + + private: + static std::map m_map; + static XMLObjectBuilder* m_default; + }; + +}; + +#if defined (_MSC_VER) + #pragma warning( pop ) +#endif + +#endif /* __xmltooling_xmlobjbuilder_h__ */ diff --git a/xmltooling/impl/AnyElement.cpp b/xmltooling/impl/AnyElement.cpp new file mode 100644 index 0000000..fea0081 --- /dev/null +++ b/xmltooling/impl/AnyElement.cpp @@ -0,0 +1,123 @@ +/* + * Copyright 2001-2006 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file AnyElement.h + * + * Advanced anyType implementation suitable for deep processing of unknown content. + */ + +#include "internal.h" +#include "AbstractAttributeExtensibleXMLObject.h" +#include "AbstractElementProxy.h" +#include "exceptions.h" +#include "impl/AnyElement.h" +#include "io/AbstractXMLObjectMarshaller.h" +#include "io/AbstractXMLObjectUnmarshaller.h" +#include "util/NDC.h" +#include "util/XMLHelper.h" + +#include +#include + +using namespace xmltooling; +using namespace log4cpp; +using namespace std; + +#if defined (_MSC_VER) + #pragma warning( push ) + #pragma warning( disable : 4250 4251 ) +#endif + +namespace xmltooling { + + /** + * Implements a smart wrapper around unknown DOM content. + */ + class XMLTOOL_DLLLOCAL AnyElementImpl : public AbstractElementProxy, public AbstractAttributeExtensibleXMLObject, + public AbstractXMLObjectMarshaller, public AbstractXMLObjectUnmarshaller + { + public: + AnyElementImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix) + : AbstractDOMCachingXMLObject(nsURI, localName, prefix), + AbstractElementProxy(nsURI, localName, prefix), + AbstractAttributeExtensibleXMLObject(nsURI, localName, prefix) {} + virtual ~AnyElementImpl() {} + + AnyElementImpl* clone() const { + auto_ptr domClone(AbstractDOMCachingXMLObject::clone()); + AnyElementImpl* ret=dynamic_cast(domClone.get()); + if (ret) { + domClone.release(); + return ret; + } + + ret=new AnyElementImpl( + getElementQName().getNamespaceURI(),getElementQName().getLocalPart(),getElementQName().getPrefix() + ); + ret->m_namespaces=m_namespaces; + for (map::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; + } + + void marshallAttributes(DOMElement* domElement) const { + for (map::const_iterator i=m_attributeMap.begin(); i!=m_attributeMap.end(); i++) { + DOMAttr* attr=domElement->getOwnerDocument()->createAttributeNS(i->first.getNamespaceURI(),i->first.getLocalPart()); + if (i->first.hasPrefix()) + attr->setPrefix(i->first.getPrefix()); + attr->setNodeValue(i->second); + domElement->setAttributeNode(attr); + } + } + + void marshallElementContent(DOMElement* domElement) const { + if(getTextContent()) { + domElement->appendChild(domElement->getOwnerDocument()->createTextNode(getTextContent())); + } + } + + void processChildElement(XMLObject* childXMLObject, const DOMElement* root) { + getXMLObjects().push_back(childXMLObject); + } + + void processAttribute(const DOMAttr* attribute) { + QName q(attribute->getNamespaceURI(),attribute->getLocalName(),attribute->getPrefix()); + setAttribute(q,attribute->getNodeValue()); + } + + void processElementContent(const XMLCh* elementContent) { + setTextContent(elementContent); + } + }; + +}; + +#if defined (_MSC_VER) + #pragma warning( pop ) +#endif + + +XMLObject* AnyElementBuilder::buildObject( + const XMLCh* namespaceURI, const XMLCh* elementLocalName, const XMLCh* namespacePrefix + ) const { + if (XMLString::stringLen(elementLocalName)==0) + throw XMLObjectException("Constructing this object requires an element name."); + return new AnyElementImpl(namespaceURI,elementLocalName,namespacePrefix); +} diff --git a/xmltooling/impl/AnyElement.h b/xmltooling/impl/AnyElement.h new file mode 100644 index 0000000..803de11 --- /dev/null +++ b/xmltooling/impl/AnyElement.h @@ -0,0 +1,48 @@ +/* + * Copyright 2001-2006 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file AnyElement.h + * + * Advanced anyType implementation suitable for deep processing of unknown content. + */ + +#if !defined(__xmltooling_anyelement_h__) +#define __xmltooling_anyelement_h__ + +#include + +namespace xmltooling { + + /** + * Implements a smart wrapper around unknown DOM content. + */ + class XMLTOOL_DLLLOCAL AnyElementImpl; + + /** + * Builder for AnyElementImpl objects. + */ + class XMLTOOL_API AnyElementBuilder : public XMLObjectBuilder + { + public: + XMLObject* buildObject( + const XMLCh* namespaceURI, const XMLCh* elementLocalName, const XMLCh* namespacePrefix=NULL + ) const; + }; + +}; + +#endif /* __xmltooling_anyelement_h__ */ diff --git a/xmltooling/impl/UnknownElement.cpp b/xmltooling/impl/UnknownElement.cpp index dd8e303..6759e5f 100644 --- a/xmltooling/impl/UnknownElement.cpp +++ b/xmltooling/impl/UnknownElement.cpp @@ -17,7 +17,7 @@ /** * UnknownElement.cpp * - * Basic implementations suitable for use as defaults for unrecognized content + * Basic implementation suitable for use as default for unrecognized content */ #include "internal.h" diff --git a/xmltooling/impl/UnknownElement.h b/xmltooling/impl/UnknownElement.h index bfc5b1a..d13f22c 100644 --- a/xmltooling/impl/UnknownElement.h +++ b/xmltooling/impl/UnknownElement.h @@ -15,18 +15,17 @@ */ /** - * UnknownElement.h + * @file UnknownElement.h * - * Basic implementations suitable for use as defaults for unrecognized content + * Basic implementation suitable for use as default for unrecognized content */ #if !defined(__xmltooling_unkelement_h__) #define __xmltooling_unkelement_h__ -#include "internal.h" -#include "XMLObjectBuilder.h" -#include "io/AbstractXMLObjectMarshaller.h" -#include "io/AbstractXMLObjectUnmarshaller.h" +#include +#include +#include #include @@ -37,6 +36,9 @@ namespace xmltooling { + /** + * Implements a thin wrapper around unknown DOM content. + */ class XMLTOOL_DLLLOCAL UnknownElementImpl : public AbstractDOMCachingXMLObject { public: @@ -65,11 +67,16 @@ namespace xmltooling { void serialize(std::string& s) const; }; - class XMLTOOL_DLLLOCAL UnknownElementBuilder : public XMLObjectBuilder + /** + * Factory for UnknownElementImpl objects. + */ + class XMLTOOL_API UnknownElementBuilder : public XMLObjectBuilder { public: - UnknownElementImpl* buildObject() const { - return new UnknownElementImpl(); + UnknownElementImpl* buildObject( + const XMLCh* namespaceURI, const XMLCh* elementLocalName, const XMLCh* namespacePrefix=NULL + ) const { + return new UnknownElementImpl(namespaceURI,elementLocalName,namespacePrefix); } }; diff --git a/xmltooling/signature/impl/XMLSecSignature.cpp b/xmltooling/signature/impl/XMLSecSignature.cpp index eb01345..7034ca3 100644 --- a/xmltooling/signature/impl/XMLSecSignature.cpp +++ b/xmltooling/signature/impl/XMLSecSignature.cpp @@ -84,11 +84,6 @@ XMLObject* XMLSecSignatureImpl::clone() const return ret; } -DSIGKeyInfoList* XMLSecSignatureImpl::getKeyInfo() const -{ - return m_signature ? m_signature->getKeyInfoList() : NULL; -} - class _addcert : public std::binary_function { public: void operator()(DSIGKeyInfoX509* bag, XSECCryptoX509* cert) const { diff --git a/xmltooling/signature/impl/XMLSecSignature.h b/xmltooling/signature/impl/XMLSecSignature.h index 635b646..e22421c 100644 --- a/xmltooling/signature/impl/XMLSecSignature.h +++ b/xmltooling/signature/impl/XMLSecSignature.h @@ -40,7 +40,7 @@ namespace xmltooling { class XMLTOOL_DLLLOCAL XMLSecSignatureImpl : public UnknownElementImpl, public virtual Signature { public: - XMLSecSignatureImpl() : UnknownElementImpl(XMLConstants::XMLSIG_NS, Signature::LOCAL_NAME), + XMLSecSignatureImpl() : UnknownElementImpl(XMLConstants::XMLSIG_NS, Signature::LOCAL_NAME, XMLConstants::XMLSIG_PREFIX), m_signature(NULL), m_c14n(NULL), m_sm(NULL) {} virtual ~XMLSecSignatureImpl(); @@ -71,7 +71,9 @@ namespace xmltooling { class XMLTOOL_DLLLOCAL XMLSecSignatureBuilder : public virtual XMLObjectBuilder { public: - XMLSecSignatureImpl* buildObject() const { + XMLSecSignatureImpl* buildObject( + const XMLCh* namespaceURI, const XMLCh* elementLocalName, const XMLCh* namespacePrefix=NULL + ) const { return new XMLSecSignatureImpl(); } }; diff --git a/xmltooling/xmltooling.vcproj b/xmltooling/xmltooling.vcproj index 11c0f60..5fc189b 100644 --- a/xmltooling/xmltooling.vcproj +++ b/xmltooling/xmltooling.vcproj @@ -253,6 +253,10 @@ Name="impl" > + + @@ -399,6 +403,10 @@ Name="impl" > + + diff --git a/xmltoolingtest/ComplexXMLObjectTest.h b/xmltoolingtest/ComplexXMLObjectTest.h index de45855..847931c 100644 --- a/xmltoolingtest/ComplexXMLObjectTest.h +++ b/xmltoolingtest/ComplexXMLObjectTest.h @@ -24,11 +24,11 @@ public: ComplexXMLObjectTest() {} void setUp() { - XMLObjectBuilder::registerDefaultBuilder(new WildcardXMLObjectBuilder()); + XMLObjectBuilder::registerDefaultBuilder(new AnyElementBuilder()); } void tearDown() { - //XMLObjectBuilder::deregisterDefaultBuilder(); + XMLObjectBuilder::deregisterDefaultBuilder(); } void testComplexUnmarshalling() { @@ -42,16 +42,16 @@ public: const XMLObjectBuilder* b = XMLObjectBuilder::getBuilder(doc->getDocumentElement()); TS_ASSERT(b!=NULL); - auto_ptr wcObject( - dynamic_cast(b->buildFromDocument(doc)) + auto_ptr wcObject( + dynamic_cast(b->buildFromDocument(doc)) ); TS_ASSERT(wcObject.get()!=NULL); ListOf(XMLObject) kids=wcObject->getXMLObjects(); TSM_ASSERT_EQUALS("Number of child elements was not expected value", 2, kids.size()); - WildcardXMLObject* wc1=dynamic_cast(*(++kids.begin())); - WildcardXMLObject* wc2=dynamic_cast(*(++(wc1->getXMLObjects().begin()))); + ElementProxy* wc1=dynamic_cast(*(++kids.begin())); + ElementProxy* wc2=dynamic_cast(*(++(wc1->getXMLObjects().begin()))); TSM_ASSERT_EQUALS("Number of child elements was not expected value", 3, wc2->getXMLObjects().size()); static const XMLCh html[] = {chLatin_h, chLatin_t, chLatin_m, chLatin_l, chNull}; diff --git a/xmltoolingtest/MarshallingTest.h b/xmltoolingtest/MarshallingTest.h index 13e07e9..af687e3 100644 --- a/xmltoolingtest/MarshallingTest.h +++ b/xmltoolingtest/MarshallingTest.h @@ -20,15 +20,19 @@ class MarshallingTest : public CxxTest::TestSuite { QName m_qname; + QName m_qtype; public: - MarshallingTest() : m_qname(SimpleXMLObject::NAMESPACE,SimpleXMLObject::LOCAL_NAME) {} + MarshallingTest() : m_qname(SimpleXMLObject::NAMESPACE,SimpleXMLObject::LOCAL_NAME,SimpleXMLObject::NAMESPACE_PREFIX), + m_qtype(SimpleXMLObject::NAMESPACE,SimpleXMLObject::TYPE_NAME,SimpleXMLObject::NAMESPACE_PREFIX) {} void setUp() { XMLObjectBuilder::registerBuilder(m_qname, new SimpleXMLObjectBuilder()); + XMLObjectBuilder::registerBuilder(m_qtype, new SimpleXMLObjectBuilder()); } void tearDown() { XMLObjectBuilder::deregisterBuilder(m_qname); + XMLObjectBuilder::deregisterBuilder(m_qtype); } void testMarshallingWithAttributes() { @@ -85,11 +89,16 @@ public: // Test some collection stuff auto_ptr_XMLCh foo("Foo"); auto_ptr_XMLCh bar("Bar"); + auto_ptr_XMLCh baz("Baz"); kids.begin()->setId(foo.get()); kids.at(2)->setValue(bar.get()); kids.erase(kids.begin()+1); TS_ASSERT_SAME_DATA(kids.back()->getValue(), bar.get(), XMLString::stringLen(bar.get())); + kids.push_back(b->buildObject(SimpleXMLObject::NAMESPACE,SimpleXMLObject::DERIVED_NAME,SimpleXMLObject::NAMESPACE_PREFIX)); + kids.back()->setSchemaType(&m_qtype); + kids.back()->setValue(baz.get()); + DOMElement* rootElement = sxObject->marshall(); string path=data_path + "SimpleXMLObjectWithChildren.xml"; diff --git a/xmltoolingtest/SignatureTest.h b/xmltoolingtest/SignatureTest.h index 5e02520..cfd8e46 100644 --- a/xmltoolingtest/SignatureTest.h +++ b/xmltoolingtest/SignatureTest.h @@ -85,15 +85,19 @@ public: class SignatureTest : public CxxTest::TestSuite { QName m_qname; + QName m_qtype; public: - SignatureTest() : m_qname(SimpleXMLObject::NAMESPACE,SimpleXMLObject::LOCAL_NAME) {} + SignatureTest() : m_qname(SimpleXMLObject::NAMESPACE,SimpleXMLObject::LOCAL_NAME,SimpleXMLObject::NAMESPACE_PREFIX), + m_qtype(SimpleXMLObject::NAMESPACE,SimpleXMLObject::TYPE_NAME,SimpleXMLObject::NAMESPACE_PREFIX) {} void setUp() { XMLObjectBuilder::registerBuilder(m_qname, new SimpleXMLObjectBuilder()); + XMLObjectBuilder::registerBuilder(m_qtype, new SimpleXMLObjectBuilder()); } void tearDown() { XMLObjectBuilder::deregisterBuilder(m_qname); + XMLObjectBuilder::deregisterBuilder(m_qtype); } void testSignature() { diff --git a/xmltoolingtest/UnmarshallingTest.h b/xmltoolingtest/UnmarshallingTest.h index d4f41cc..fe8487b 100644 --- a/xmltoolingtest/UnmarshallingTest.h +++ b/xmltoolingtest/UnmarshallingTest.h @@ -37,21 +37,36 @@ const XMLCh SimpleXMLObject::LOCAL_NAME[] = { chLatin_E, chLatin_l, chLatin_e, chLatin_m, chLatin_e, chLatin_n, chLatin_t, chNull }; +const XMLCh SimpleXMLObject::DERIVED_NAME[] = { + chLatin_D, chLatin_e, chLatin_r, chLatin_i, chLatin_v, chLatin_e, chLatin_d, + chLatin_E, chLatin_l, chLatin_e, chLatin_m, chLatin_e, chLatin_n, chLatin_t, chNull +}; + +const XMLCh SimpleXMLObject::TYPE_NAME[] = { + chLatin_S, chLatin_i, chLatin_m, chLatin_p, chLatin_l, chLatin_e, + chLatin_E, chLatin_l, chLatin_e, chLatin_m, chLatin_e, chLatin_n, chLatin_t, + chLatin_T, chLatin_y, chLatin_p, chLatin_e, chNull +}; + const XMLCh SimpleXMLObject::ID_ATTRIB_NAME[] = { chLatin_I, chLatin_d, chNull }; class UnmarshallingTest : public CxxTest::TestSuite { QName m_qname; + QName m_qtype; public: - UnmarshallingTest() : m_qname(SimpleXMLObject::NAMESPACE,SimpleXMLObject::LOCAL_NAME) {} + UnmarshallingTest() : m_qname(SimpleXMLObject::NAMESPACE,SimpleXMLObject::LOCAL_NAME,SimpleXMLObject::NAMESPACE_PREFIX), + m_qtype(SimpleXMLObject::NAMESPACE,SimpleXMLObject::TYPE_NAME,SimpleXMLObject::NAMESPACE_PREFIX) {} void setUp() { XMLObjectBuilder::registerBuilder(m_qname, new SimpleXMLObjectBuilder()); + XMLObjectBuilder::registerBuilder(m_qtype, new SimpleXMLObjectBuilder()); } void tearDown() { XMLObjectBuilder::deregisterBuilder(m_qname); + XMLObjectBuilder::deregisterBuilder(m_qtype); } void testUnmarshallingWithAttributes() { @@ -111,7 +126,8 @@ public: TS_ASSERT(sxObject.get()!=NULL); VectorOf(SimpleXMLObject) kids=sxObject->getSimpleXMLObjects(); - TSM_ASSERT_EQUALS("Number of child elements was not expected value", 2, kids.size()); + TSM_ASSERT_EQUALS("Number of child elements was not expected value", 3, kids.size()); + TSM_ASSERT_EQUALS("Child's schema type was not expected value", m_qtype, *(kids.back()->getSchemaType())); } void testUnmarshallingWithUnknownChild() { diff --git a/xmltoolingtest/XMLObjectBaseTestCase.h b/xmltoolingtest/XMLObjectBaseTestCase.h index 873f227..e9cface 100644 --- a/xmltoolingtest/XMLObjectBaseTestCase.h +++ b/xmltoolingtest/XMLObjectBaseTestCase.h @@ -15,13 +15,14 @@ */ #include -#include -#include +#include #include #include #include #include #include +#include +#include #ifndef XMLTOOLING_NO_XMLSEC #include #endif @@ -48,9 +49,13 @@ public: static const XMLCh NAMESPACE[]; static const XMLCh NAMESPACE_PREFIX[]; static const XMLCh LOCAL_NAME[]; + static const XMLCh DERIVED_NAME[]; + static const XMLCh TYPE_NAME[]; static const XMLCh ID_ATTRIB_NAME[]; - SimpleXMLObject() : AbstractDOMCachingXMLObject(NAMESPACE, LOCAL_NAME, NAMESPACE_PREFIX), m_id(NULL), m_value(NULL) { + SimpleXMLObject( + const XMLCh* namespaceURI=NULL, const XMLCh* elementLocalName=NULL, const XMLCh* namespacePrefix=NULL + ) : AbstractDOMCachingXMLObject(namespaceURI, elementLocalName, namespacePrefix), m_id(NULL), m_value(NULL) { #ifndef XMLTOOLING_NO_XMLSEC m_children.push_back(NULL); m_signature=m_children.begin(); @@ -112,14 +117,21 @@ public: } void processChildElement(XMLObject* childXMLObject, const DOMElement* root) { - if (XMLHelper::isNodeNamed(root, SimpleXMLObject::NAMESPACE, SimpleXMLObject::LOCAL_NAME)) - getSimpleXMLObjects().push_back(dynamic_cast(childXMLObject)); + SimpleXMLObject* simple=dynamic_cast(childXMLObject); + if (simple) { + getSimpleXMLObjects().push_back(simple); + return; + } + #ifndef XMLTOOLING_NO_XMLSEC - else if (XMLHelper::isNodeNamed(root, XMLConstants::XMLSIG_NS, Signature::LOCAL_NAME)) - setSignature(dynamic_cast(childXMLObject)); + Signature* sig=dynamic_cast(childXMLObject); + if (sig) { + setSignature(sig); + return; + } #endif - else - throw UnmarshallingException("Unknown child element cannot be added to parent object."); + + throw UnmarshallingException("Unknown child element cannot be added to parent object."); } void processAttribute(const DOMAttr* attribute) { @@ -146,85 +158,13 @@ class SimpleXMLObjectBuilder : public XMLObjectBuilder { public: SimpleXMLObject* buildObject() const { - return new SimpleXMLObject(); - } -}; - -class WildcardXMLObject : public AbstractElementProxy, public AbstractAttributeExtensibleXMLObject, - public AbstractXMLObjectMarshaller, public AbstractXMLObjectUnmarshaller -{ -public: - WildcardXMLObject(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix) - : AbstractDOMCachingXMLObject(nsURI, localName, prefix), - AbstractElementProxy(nsURI, localName, prefix), - AbstractAttributeExtensibleXMLObject(nsURI, localName, prefix) {} - virtual ~WildcardXMLObject() {} - - WildcardXMLObject* clone() const { - auto_ptr domClone(AbstractDOMCachingXMLObject::clone()); - WildcardXMLObject* ret=dynamic_cast(domClone.get()); - if (ret) { - domClone.release(); - return ret; - } - - ret=new WildcardXMLObject( - getElementQName().getNamespaceURI(),getElementQName().getLocalPart(),getElementQName().getPrefix() - ); - ret->m_namespaces=m_namespaces; - for (map::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; - } - - void marshallAttributes(DOMElement* domElement) const { - for (map::const_iterator i=m_attributeMap.begin(); i!=m_attributeMap.end(); i++) { - DOMAttr* attr=domElement->getOwnerDocument()->createAttributeNS(i->first.getNamespaceURI(),i->first.getLocalPart()); - if (i->first.hasPrefix()) - attr->setPrefix(i->first.getPrefix()); - attr->setNodeValue(i->second); - domElement->setAttributeNode(attr); - } - } - - void marshallElementContent(DOMElement* domElement) const { - if(getTextContent()) { - domElement->appendChild(domElement->getOwnerDocument()->createTextNode(getTextContent())); - } - } - - void processChildElement(XMLObject* childXMLObject, const DOMElement* root) { - getXMLObjects().push_back(childXMLObject); - } - - void processAttribute(const DOMAttr* attribute) { - QName q(attribute->getNamespaceURI(),attribute->getLocalName(),attribute->getPrefix()); - setAttribute(q,attribute->getNodeValue()); - } - - void processElementContent(const XMLCh* elementContent) { - setTextContent(elementContent); - } -}; - -class WildcardXMLObjectBuilder : public XMLObjectBuilder -{ -public: - WildcardXMLObject* buildObject() const { - throw XMLObjectException("Default build operation is unsupported."); - } - - WildcardXMLObject* buildObject(const QName& q) const { - return new WildcardXMLObject(q.getNamespaceURI(),q.getLocalPart(),q.getPrefix()); + return buildObject(SimpleXMLObject::NAMESPACE, SimpleXMLObject::LOCAL_NAME, SimpleXMLObject::NAMESPACE_PREFIX); } - WildcardXMLObject* buildFromElement(DOMElement* e, bool bindDocument=false) const { - auto_ptr ret(new WildcardXMLObject(e->getNamespaceURI(),e->getLocalName(),e->getPrefix())); - ret->unmarshall(e,bindDocument); - return ret.release(); + SimpleXMLObject* buildObject( + const XMLCh* namespaceURI, const XMLCh* elementLocalName, const XMLCh* namespacePrefix=NULL + ) const { + return new SimpleXMLObject(namespaceURI,elementLocalName,namespacePrefix); } }; diff --git a/xmltoolingtest/data/SimpleXMLObjectWithChildren.xml b/xmltoolingtest/data/SimpleXMLObjectWithChildren.xml index f8a9f67..9a6769b 100644 Binary files a/xmltoolingtest/data/SimpleXMLObjectWithChildren.xml and b/xmltoolingtest/data/SimpleXMLObjectWithChildren.xml differ diff --git a/xmltoolingtest/xmltoolingtest.h b/xmltoolingtest/xmltoolingtest.h index 84b52c1..fcf5a69 100644 --- a/xmltoolingtest/xmltoolingtest.h +++ b/xmltoolingtest/xmltoolingtest.h @@ -62,6 +62,14 @@ static ToolingFixture globalFixture; class GlobalTest : public CxxTest::TestSuite { public: + void setUp() { + XMLObjectBuilder::registerDefaultBuilder(new UnknownElementBuilder()); + } + + void tearDown() { + XMLObjectBuilder::deregisterDefaultBuilder(); + } + void testCatalog(void) { std::string path=data_path + "catalog.xml"; auto_ptr_XMLCh temp(path.c_str());