From 13aedf637c24ba2d641e49edfcc7067861eed040 Mon Sep 17 00:00:00 2001 From: "Zane U. Ji" Date: Tue, 22 Apr 2014 22:17:53 +0800 Subject: [PATCH] Fixed problems when generating schemas --- src/xmlschemagenerator.cpp | 64 ++++++++++++++++++++++++-------------- src/xmlschemagenerator.h | 7 +++-- 2 files changed, 45 insertions(+), 26 deletions(-) diff --git a/src/xmlschemagenerator.cpp b/src/xmlschemagenerator.cpp index 4a3104d..89b37df 100644 --- a/src/xmlschemagenerator.cpp +++ b/src/xmlschemagenerator.cpp @@ -148,22 +148,33 @@ void XmlSchemaGenerator::generateData ( const wxString &elementName, //Content std::map &childMap = data.children; std::map::iterator itr; - std::set previous; + std::set precedence; elmtItr = data.nodes.begin(); for ( ; elmtItr != data.nodes.end(); ++elmtItr ) { - previous.clear(); - std::map countMap; - DOMElement *child = ( **elmtItr ).getFirstElementChild(); - for ( ; child != NULL; child = child->getNextElementSibling() ) + DOMNode *child = ( **elmtItr ).getFirstChild(); + for ( ; child != NULL; child = child->getNextSibling() ) { - wxString name = WrapXerces::toString ( child->getTagName() ); - childMap[name].prevSiblings.insert ( previous.begin(), previous.end() ); - childMap[name].prevSiblings.erase ( name ); // Don't depend on oneself - previous.insert ( name ); + DOMNode::NodeType type = child->getNodeType(); + if ( type != DOMNode::ELEMENT_NODE ) + { + if ( type == DOMNode::TEXT_NODE ) + { // Check for mixed content + wxString value = WrapXerces::toString ( child->getNodeValue() ); + if ( !value.Trim().Trim ( false ).empty() ) + data.mixed = true; + } + continue; + } + wxString name = WrapXerces::toString ( child->getNodeName() ); + childMap[name].precedence.insert ( precedence.begin(), precedence.end() ); + childMap[name].precedence.erase ( name ); // Don't depend on oneself + precedence.insert ( name ); countMap[name] += 1; } + precedence.clear(); + std::map::iterator countItr = countMap.begin(); for ( ; countItr != countMap.end(); ++countItr ) { @@ -186,12 +197,16 @@ void XmlSchemaGenerator::generateData ( const wxString &elementName, elmtItr = data.nodes.begin(); for ( ; elmtItr != data.nodes.end(); ++elmtItr ) { - if ( ! ( **elmtItr ).hasAttributes() ) + DOMNamedNodeMap *attrs = ( **elmtItr ).getAttributes(); + if ( attrs == NULL ) + { + for ( attrItr = attrMap.begin(); attrItr != attrMap.end(); ++attrItr ) + optAttrs.insert ( attrItr->first ); continue; + } wxString name; DOMAttr *attr; - DOMNamedNodeMap *attrs = ( **elmtItr ).getAttributes(); size_t i = attrs->getLength(); while ( i-- > 0 ) { @@ -202,6 +217,9 @@ void XmlSchemaGenerator::generateData ( const wxString &elementName, wxLogDebug ( _T("Ignore: %s"), name.c_str() ); continue; } + if ( elmtItr != data.nodes.begin() ) // Not the first node + if ( attrMap.find ( name ) == attrMap.end() ) // Not in the map + optAttrs.insert ( name ); if ( attr->getSpecified() ) attrMap[name]; // Initialize attribute map else @@ -275,12 +293,13 @@ void XmlSchemaGenerator::generateSchema ( ElmtData &data, size_t nIndent ) addIndent ( schema, nIndent++ ); schema << _T("") << getEOL(); + addIndent ( schema, nIndent++ ); + if ( data.mixed ) + schema << _T("") << getEOL(); + else + schema << _T("") << getEOL(); if ( !data.children.empty() ) { - addIndent ( schema, nIndent++ ); - schema << _T("") << getEOL(); - addIndent ( schema, nIndent++ ); - size_t minOccurs = 1, maxOccurs = 1, minTotal = 0; std::map::const_iterator itr; for ( itr = data.children.begin(); itr != data.children.end(); ++itr ) @@ -291,6 +310,7 @@ void XmlSchemaGenerator::generateSchema ( ElmtData &data, size_t nIndent ) maxOccurs = itr->second.maxOccurs; minTotal += itr->second.minOccurs; } + addIndent ( schema, nIndent++ ); if ( data.useSequence ) { schema << _T("") << getEOL(); } - } - else if ( !data.attrMap.empty() ) - { - addIndent ( schema, nIndent++ ); - schema << _T("") << getEOL(); - } + } // Child elements + std::map::const_iterator attrItr; attrItr = data.attrMap.begin(); for ( ; attrItr != data.attrMap.end(); ++attrItr ) @@ -468,8 +484,8 @@ bool XmlSchemaGenerator::getSequence ( std::vector &sequence, continue; seqItr = sequence.begin(); - prevItr = itr->second.prevSiblings.begin(); - prevEnd = itr->second.prevSiblings.end(); + prevItr = itr->second.precedence.begin(); + prevEnd = itr->second.precedence.end(); for ( ; prevItr != prevEnd; ++prevItr ) { // Find last index of dependent elements seqFindItr = std::find ( sequence.begin(), sequence.end(), @@ -483,7 +499,7 @@ bool XmlSchemaGenerator::getSequence ( std::vector &sequence, continue; } const std::set &previous = - elmtMap.find ( *prevItr )->second.prevSiblings; + elmtMap.find ( *prevItr )->second.precedence; if ( previous.find ( itr->first ) == previous.end() ) { // Not a deadlock retry = true; diff --git a/src/xmlschemagenerator.h b/src/xmlschemagenerator.h index 3a286ac..f99315a 100644 --- a/src/xmlschemagenerator.h +++ b/src/xmlschemagenerator.h @@ -55,12 +55,12 @@ protected: public: ChildData() : minOccurs ( 1 ), maxOccurs ( 1 ) {} size_t minOccurs, maxOccurs; - std::set prevSiblings; + std::set precedence; }; class ElmtData { public: - ElmtData() : useSequence ( true ) { } + ElmtData() : useSequence ( true ), mixed ( false ) { } // All occurs std::set nodes; @@ -73,6 +73,9 @@ protected: // Sequence of children std::vector sequence; bool useSequence; // Use xs:sequence or xs:choice + // Specifies whether character data is allowed to appear between the + // child elements of this complexType element + bool mixed; // Attribute name and default value std::map attrMap; // Optional attributes