From f6221acce6ee490b9189dd2f5efabda3b9e64fb1 Mon Sep 17 00:00:00 2001 From: Scott Cantor Date: Fri, 14 Mar 2008 01:14:23 +0000 Subject: [PATCH] Multi-line svn commit, see body. Add xsi:nil support to objects. Add basic check for nil validity to validator macros. --- xmltooling/AbstractXMLObject.cpp | 29 +++++++++++++-- xmltooling/AbstractXMLObject.h | 18 +++++++++- xmltooling/XMLObject.h | 48 +++++++++++++++++++++++++ xmltooling/base.h | 6 ++-- xmltooling/io/AbstractXMLObjectMarshaller.cpp | 21 +++++++++++ xmltooling/io/AbstractXMLObjectUnmarshaller.cpp | 6 ++++ xmltoolingtest/data/ComplexXMLObject.xml | 1 + 7 files changed, 124 insertions(+), 5 deletions(-) diff --git a/xmltooling/AbstractXMLObject.cpp b/xmltooling/AbstractXMLObject.cpp index 7c73f3f..6448856 100644 --- a/xmltooling/AbstractXMLObject.cpp +++ b/xmltooling/AbstractXMLObject.cpp @@ -29,7 +29,8 @@ using namespace xmltooling; AbstractXMLObject::AbstractXMLObject(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType) - : m_log(logging::Category::getInstance(XMLTOOLING_LOGCAT".XMLObject")), m_schemaLocation(NULL), m_noNamespaceSchemaLocation(NULL), + : m_log(logging::Category::getInstance(XMLTOOLING_LOGCAT".XMLObject")), + m_schemaLocation(NULL), m_noNamespaceSchemaLocation(NULL), m_nil(xmlconstants::XML_BOOL_NULL), m_parent(NULL), m_elementQname(nsURI, localName, prefix), m_typeQname(NULL) { addNamespace(Namespace(nsURI, prefix)); @@ -41,13 +42,37 @@ AbstractXMLObject::AbstractXMLObject(const XMLCh* nsURI, const XMLCh* localName, AbstractXMLObject::AbstractXMLObject(const AbstractXMLObject& src) : m_namespaces(src.m_namespaces), m_log(src.m_log), m_schemaLocation(XMLString::replicate(src.m_schemaLocation)), - m_noNamespaceSchemaLocation(XMLString::replicate(src.m_noNamespaceSchemaLocation)), + m_noNamespaceSchemaLocation(XMLString::replicate(src.m_noNamespaceSchemaLocation)), m_nil(src.m_nil), m_parent(NULL), m_elementQname(src.m_elementQname), m_typeQname(NULL) { if (src.m_typeQname) m_typeQname=new QName(*src.m_typeQname); } +void XMLObject::setNil(const XMLCh* value) { + if (value) { + switch (*value) { + case xercesc::chLatin_t: + nil(xmlconstants::XML_BOOL_TRUE); + break; + case xercesc::chLatin_f: + nil(xmlconstants::XML_BOOL_FALSE); + break; + case xercesc::chDigit_1: + nil(xmlconstants::XML_BOOL_ONE); + break; + case xercesc::chDigit_0: + nil(xmlconstants::XML_BOOL_ZERO); + break; + default: + nil(xmlconstants::XML_BOOL_NULL); + } + } + else { + nil(xmlconstants::XML_BOOL_NULL); + } +} + XMLCh* AbstractXMLObject::prepareForAssignment(XMLCh* oldValue, const XMLCh* newValue) { if (!XMLString::equals(oldValue,newValue)) { diff --git a/xmltooling/AbstractXMLObject.h b/xmltooling/AbstractXMLObject.h index 3b41d6d..7767167 100644 --- a/xmltooling/AbstractXMLObject.h +++ b/xmltooling/AbstractXMLObject.h @@ -79,7 +79,18 @@ namespace xmltooling { const XMLCh* getXMLID() const { return NULL; } - + + xmlconstants::xmltooling_bool_t getNil() const { + return m_nil; + } + + void nil(xmlconstants::xmltooling_bool_t value) { + if (m_nil != value) { + releaseThisandParentDOM(); + m_nil = value; + } + } + bool hasParent() const { return m_parent != NULL; } @@ -205,6 +216,11 @@ namespace xmltooling { * Stores off xsi:noNamespaceSchemaLocation attribute. */ XMLCh* m_noNamespaceSchemaLocation; + + /** + * Stores off xsi:nil attribute. + */ + xmlconstants::xmltooling_bool_t m_nil; private: XMLObject* m_parent; diff --git a/xmltooling/XMLObject.h b/xmltooling/XMLObject.h index 176a973..85f7054 100644 --- a/xmltooling/XMLObject.h +++ b/xmltooling/XMLObject.h @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -124,6 +125,53 @@ namespace xmltooling { * @return an ID value or NULL */ virtual const XMLCh* getXMLID() const=0; + + /** + * Returns the xsi:nil property of the object, or false if not set. + * + * @return the xsi:nil property + */ + bool nil() const { + switch (getNil()) { + case xmlconstants::XML_BOOL_TRUE: + case xmlconstants::XML_BOOL_ONE: + return true; + case xmlconstants::XML_BOOL_FALSE: + case xmlconstants::XML_BOOL_ZERO: + default: + return false; + } + } + + /** + * Returns the xsi:nil property as an explicit enumerated value. + * + * @return the xsi:nil property + */ + virtual xmlconstants::xmltooling_bool_t getNil() const=0; + + /** + * Sets the xsi:nil property using an enumerated value. + * + * @param value value to set + */ + virtual void nil(xmlconstants::xmltooling_bool_t value)=0; + + /** + * Sets the xsi:nil property. + * + * @param value value to set + */ + void nil(bool value) { + nil(value ? xmlconstants::XML_BOOL_ONE : xmlconstants::XML_BOOL_ZERO); + } + + /** + * Sets the xsi:nil property using a string constant. + * + * @param value value to set + */ + void setNil(const XMLCh* value); /** * Checks to see if this object has a parent. diff --git a/xmltooling/base.h b/xmltooling/base.h index 4936a8a..b6d3ba3 100644 --- a/xmltooling/base.h +++ b/xmltooling/base.h @@ -1354,7 +1354,9 @@ virtual void validate(const xmltooling::XMLObject* xmlObject) const { \ const cname* ptr=dynamic_cast(xmlObject); \ if (!ptr) \ - throw xmltooling::ValidationException(#cname"SchemaValidator: unsupported object type ($1).",xmltooling::params(1,typeid(xmlObject).name())) + throw xmltooling::ValidationException(#cname"SchemaValidator: unsupported object type ($1).",xmltooling::params(1,typeid(xmlObject).name())); \ + if (ptr->nil() && (ptr->hasChildren() || ptr->getTextContent())) \ + throw xmltooling::ValidationException("Object has nil property but with children or content.") /** * Begins the declaration of a Schema Validator specialization subclass. @@ -1371,7 +1373,7 @@ virtual void validate(const xmltooling::XMLObject* xmlObject) const { \ const cname* ptr=dynamic_cast(xmlObject); \ if (!ptr) \ - throw xmltooling::ValidationException(#cname"SchemaValidator: unsupported object type ($1).",xmltooling::params(1,typeid(xmlObject).name())) + throw xmltooling::ValidationException(#cname"SchemaValidator: unsupported object type ($1).",xmltooling::params(1,typeid(xmlObject).name())); /** * Ends the declaration of a Validator specialization. diff --git a/xmltooling/io/AbstractXMLObjectMarshaller.cpp b/xmltooling/io/AbstractXMLObjectMarshaller.cpp index 0c87aff..622240d 100644 --- a/xmltooling/io/AbstractXMLObjectMarshaller.cpp +++ b/xmltooling/io/AbstractXMLObjectMarshaller.cpp @@ -192,6 +192,27 @@ void AbstractXMLObjectMarshaller::marshallInto( targetElement->setAttributeNS(XSI_NS,noNamespaceSchemaLocation,m_noNamespaceSchemaLocation); } } + + static const XMLCh _nil[] = { chLatin_x, chLatin_s, chLatin_i, chColon, chLatin_n, chLatin_i, chLatin_l, chNull }; + + if (m_nil != xmlconstants::XML_BOOL_NULL) { + switch (m_nil) { + case xmlconstants::XML_BOOL_TRUE: + targetElement->setAttributeNS(XSI_NS, _nil, xmlconstants::XML_TRUE); + break; + case xmlconstants::XML_BOOL_ONE: + targetElement->setAttributeNS(XSI_NS, _nil, xmlconstants::XML_ONE); + break; + case xmlconstants::XML_BOOL_FALSE: + targetElement->setAttributeNS(XSI_NS, _nil, xmlconstants::XML_FALSE); + break; + case xmlconstants::XML_BOOL_ZERO: + targetElement->setAttributeNS(XSI_NS, _nil, xmlconstants::XML_ZERO); + break; + } + m_log.debug("adding XSI namespace to list of namespaces used by XMLObject"); + addNamespace(Namespace(XSI_NS, XSI_PREFIX)); + } marshallElementType(targetElement); marshallNamespaces(targetElement); diff --git a/xmltooling/io/AbstractXMLObjectUnmarshaller.cpp b/xmltooling/io/AbstractXMLObjectUnmarshaller.cpp index 6bc173d..5a07591 100644 --- a/xmltooling/io/AbstractXMLObjectUnmarshaller.cpp +++ b/xmltooling/io/AbstractXMLObjectUnmarshaller.cpp @@ -111,6 +111,7 @@ void AbstractXMLObjectUnmarshaller::unmarshallAttributes(const DOMElement* domEl static const XMLCh type[]= UNICODE_LITERAL_4(t,y,p,e); static const XMLCh schemaLocation[]= UNICODE_LITERAL_14(s,c,h,e,m,a,L,o,c,a,t,i,o,n); static const XMLCh noNamespaceSchemaLocation[]= UNICODE_LITERAL_25(n,o,N,a,m,e,s,p,a,c,e,S,c,h,e,m,a,L,o,c,a,t,i,o,n); + static const XMLCh _nil[]= UNICODE_LITERAL_3(n,i,l); if (XMLString::equals(attribute->getLocalName(),type)) { m_log.debug("skipping xsi:type declaration"); continue; @@ -130,6 +131,11 @@ void AbstractXMLObjectUnmarshaller::unmarshallAttributes(const DOMElement* domEl m_noNamespaceSchemaLocation=XMLString::replicate(attribute->getValue()); continue; } + else if (XMLString::equals(attribute->getLocalName(), _nil)) { + m_log.debug("processing xsi:nil attribute"); + setNil(attribute->getValue()); + continue; + } } else if (nsuri && !XMLString::equals(nsuri,XML_NS)) { m_log.debug("found namespace-qualified attribute, adding prefix to the list of namespaces on the XMLObject"); diff --git a/xmltoolingtest/data/ComplexXMLObject.xml b/xmltoolingtest/data/ComplexXMLObject.xml index 7b97ccb..f93c5d9 100644 --- a/xmltoolingtest/data/ComplexXMLObject.xml +++ b/xmltoolingtest/data/ComplexXMLObject.xml @@ -2,6 +2,7 @@ Python Perfect IDE + Uses mind-reading technology to anticipate and accommodate all user needs in Python development. Implements all -- 2.1.4