Fixed problems when generating schemas

This commit is contained in:
Zane U. Ji 2014-04-22 22:17:53 +08:00
parent da89b9cbe6
commit 13aedf637c
2 changed files with 45 additions and 26 deletions

View File

@ -148,22 +148,33 @@ void XmlSchemaGenerator::generateData ( const wxString &elementName,
//Content //Content
std::map<wxString, ChildData> &childMap = data.children; std::map<wxString, ChildData> &childMap = data.children;
std::map<wxString, ChildData>::iterator itr; std::map<wxString, ChildData>::iterator itr;
std::set<wxString> previous; std::set<wxString> precedence;
elmtItr = data.nodes.begin(); elmtItr = data.nodes.begin();
for ( ; elmtItr != data.nodes.end(); ++elmtItr ) for ( ; elmtItr != data.nodes.end(); ++elmtItr )
{ {
previous.clear();
std::map<wxString, size_t> countMap; std::map<wxString, size_t> countMap;
DOMElement *child = ( **elmtItr ).getFirstElementChild(); DOMNode *child = ( **elmtItr ).getFirstChild();
for ( ; child != NULL; child = child->getNextElementSibling() ) for ( ; child != NULL; child = child->getNextSibling() )
{ {
wxString name = WrapXerces::toString ( child->getTagName() ); DOMNode::NodeType type = child->getNodeType();
childMap[name].prevSiblings.insert ( previous.begin(), previous.end() ); if ( type != DOMNode::ELEMENT_NODE )
childMap[name].prevSiblings.erase ( name ); // Don't depend on oneself {
previous.insert ( name ); 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; countMap[name] += 1;
} }
precedence.clear();
std::map<wxString, size_t>::iterator countItr = countMap.begin(); std::map<wxString, size_t>::iterator countItr = countMap.begin();
for ( ; countItr != countMap.end(); ++countItr ) for ( ; countItr != countMap.end(); ++countItr )
{ {
@ -186,12 +197,16 @@ void XmlSchemaGenerator::generateData ( const wxString &elementName,
elmtItr = data.nodes.begin(); elmtItr = data.nodes.begin();
for ( ; elmtItr != data.nodes.end(); ++elmtItr ) 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; continue;
}
wxString name; wxString name;
DOMAttr *attr; DOMAttr *attr;
DOMNamedNodeMap *attrs = ( **elmtItr ).getAttributes();
size_t i = attrs->getLength(); size_t i = attrs->getLength();
while ( i-- > 0 ) while ( i-- > 0 )
{ {
@ -202,6 +217,9 @@ void XmlSchemaGenerator::generateData ( const wxString &elementName,
wxLogDebug ( _T("Ignore: %s"), name.c_str() ); wxLogDebug ( _T("Ignore: %s"), name.c_str() );
continue; 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() ) if ( attr->getSpecified() )
attrMap[name]; // Initialize attribute map attrMap[name]; // Initialize attribute map
else else
@ -275,12 +293,13 @@ void XmlSchemaGenerator::generateSchema ( ElmtData &data, size_t nIndent )
addIndent ( schema, nIndent++ ); addIndent ( schema, nIndent++ );
schema << _T("<xs:element name=\"") << data.name << _T("\">") << getEOL(); schema << _T("<xs:element name=\"") << data.name << _T("\">") << getEOL();
addIndent ( schema, nIndent++ );
if ( data.mixed )
schema << _T("<xs:complexType mixed=\"true\">") << getEOL();
else
schema << _T("<xs:complexType>") << getEOL();
if ( !data.children.empty() ) if ( !data.children.empty() )
{ {
addIndent ( schema, nIndent++ );
schema << _T("<xs:complexType>") << getEOL();
addIndent ( schema, nIndent++ );
size_t minOccurs = 1, maxOccurs = 1, minTotal = 0; size_t minOccurs = 1, maxOccurs = 1, minTotal = 0;
std::map<wxString, ChildData>::const_iterator itr; std::map<wxString, ChildData>::const_iterator itr;
for ( itr = data.children.begin(); itr != data.children.end(); ++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; maxOccurs = itr->second.maxOccurs;
minTotal += itr->second.minOccurs; minTotal += itr->second.minOccurs;
} }
addIndent ( schema, nIndent++ );
if ( data.useSequence ) if ( data.useSequence )
{ {
schema << _T("<xs:sequence"); schema << _T("<xs:sequence");
@ -345,12 +365,8 @@ void XmlSchemaGenerator::generateSchema ( ElmtData &data, size_t nIndent )
{ {
schema << _T("</xs:choice>") << getEOL(); schema << _T("</xs:choice>") << getEOL();
} }
} } // Child elements
else if ( !data.attrMap.empty() )
{
addIndent ( schema, nIndent++ );
schema << _T("<xs:complexType>") << getEOL();
}
std::map<wxString, const XMLCh *>::const_iterator attrItr; std::map<wxString, const XMLCh *>::const_iterator attrItr;
attrItr = data.attrMap.begin(); attrItr = data.attrMap.begin();
for ( ; attrItr != data.attrMap.end(); ++attrItr ) for ( ; attrItr != data.attrMap.end(); ++attrItr )
@ -468,8 +484,8 @@ bool XmlSchemaGenerator::getSequence ( std::vector<wxString> &sequence,
continue; continue;
seqItr = sequence.begin(); seqItr = sequence.begin();
prevItr = itr->second.prevSiblings.begin(); prevItr = itr->second.precedence.begin();
prevEnd = itr->second.prevSiblings.end(); prevEnd = itr->second.precedence.end();
for ( ; prevItr != prevEnd; ++prevItr ) for ( ; prevItr != prevEnd; ++prevItr )
{ // Find last index of dependent elements { // Find last index of dependent elements
seqFindItr = std::find ( sequence.begin(), sequence.end(), seqFindItr = std::find ( sequence.begin(), sequence.end(),
@ -483,7 +499,7 @@ bool XmlSchemaGenerator::getSequence ( std::vector<wxString> &sequence,
continue; continue;
} }
const std::set<wxString> &previous = const std::set<wxString> &previous =
elmtMap.find ( *prevItr )->second.prevSiblings; elmtMap.find ( *prevItr )->second.precedence;
if ( previous.find ( itr->first ) == previous.end() ) if ( previous.find ( itr->first ) == previous.end() )
{ // Not a deadlock { // Not a deadlock
retry = true; retry = true;

View File

@ -55,12 +55,12 @@ protected:
public: public:
ChildData() : minOccurs ( 1 ), maxOccurs ( 1 ) {} ChildData() : minOccurs ( 1 ), maxOccurs ( 1 ) {}
size_t minOccurs, maxOccurs; size_t minOccurs, maxOccurs;
std::set<wxString> prevSiblings; std::set<wxString> precedence;
}; };
class ElmtData class ElmtData
{ {
public: public:
ElmtData() : useSequence ( true ) { } ElmtData() : useSequence ( true ), mixed ( false ) { }
// All occurs // All occurs
std::set<const DOMElement*> nodes; std::set<const DOMElement*> nodes;
@ -73,6 +73,9 @@ protected:
// Sequence of children // Sequence of children
std::vector<wxString> sequence; std::vector<wxString> sequence;
bool useSequence; // Use xs:sequence or xs:choice 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 // Attribute name and default value
std::map<wxString, const XMLCh *> attrMap; std::map<wxString, const XMLCh *> attrMap;
// Optional attributes // Optional attributes