From 448760cbdb8f1ee1f3eb3559c7b05e7a61e37a88 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 8 Jan 2010 14:04:58 +0200 Subject: Resolve namespace for default/fixed values of QName type --- xsd-frontend/parser.cxx | 228 ++++++++++++++++++++++++++++++++++++++++++++++-- xsd-frontend/xml.hxx | 42 +++++++-- 2 files changed, 256 insertions(+), 14 deletions(-) (limited to 'xsd-frontend') diff --git a/xsd-frontend/parser.cxx b/xsd-frontend/parser.cxx index bcdf0a6..990f75b 100644 --- a/xsd-frontend/parser.cxx +++ b/xsd-frontend/parser.cxx @@ -13,6 +13,7 @@ #include #include +#include #include //@@ Do i need this? @@ -120,6 +121,7 @@ namespace XSDFrontend typedef Cult::Containers::Map NodeMap; typedef Cult::Containers::Map NamespaceMap; + typedef Cult::Containers::Vector DefaultValues; template X& @@ -304,8 +306,14 @@ namespace XSDFrontend Traversal::AttributeGroup, Traversal::Compositor { - Resolver (Schema& s, Boolean& valid, NamespaceMap& cache) - : s_ (s), valid_ (valid), cache_ (cache) + Resolver (Schema& s, + Boolean& valid, + NamespaceMap& cache, + DefaultValues& default_values) + : s_ (s), + valid_ (valid), + cache_ (cache), + default_values_ (default_values) { *this >> contains_compositor >> *this; } @@ -458,6 +466,14 @@ namespace XSDFrontend m.fixed (ref.value ()); else if (ref.default_ ()) m.default_ (ref.value ()); + + if (m.default_ ()) + { + m.context ().set ( + "dom-node", + ref.context ().get ("dom-node")); + default_values_.push_back (&m); + } } // Transfer annotation if we haven't already gotten it. @@ -1011,6 +1027,14 @@ namespace XSDFrontend else if (e.default_ ()) copy.default_ (e.value ()); + if (copy.default_ ()) + { + copy.context ().set ( + "dom-node", + e.context ().get ("dom-node")); + default_values_.push_back (©); + } + // Transfer annotation. // if (e.annotated ()) @@ -1077,6 +1101,14 @@ namespace XSDFrontend else if (p->default_ ()) a.default_ (p->value ()); + if (a.default_ ()) + { + a.context ().set ( + "dom-node", + p->context ().get ("dom-node")); + default_values_.push_back (&a); + } + // Transfer annotation. // if (p->annotated ()) @@ -1155,6 +1187,7 @@ namespace XSDFrontend Schema& s_; Boolean& valid_; NamespaceMap& cache_; + DefaultValues& default_values_; private: //Traversal::ContainsParticle contains_particle; @@ -1433,7 +1466,7 @@ namespace XSDFrontend // be assigned to a namespace (which takes precedence over names // without a namespace). // - return XML::ns_name (e, p); + return XML::ns_name (e.dom_element (), p); } catch (XML::NoMapping const& ex) { @@ -1444,12 +1477,44 @@ namespace XSDFrontend } } + SemanticGraph::Type& + ultimate_base (SemanticGraph::Type& t) + { + using namespace SemanticGraph; + + Complex* c = dynamic_cast (&t); + + if (c != 0 && c->inherits_p ()) + { + Type* b (&c->inherits ().base ()); + + while (true) + { + Complex* cb (dynamic_cast (b)); + + if (cb != 0 && cb->inherits_p ()) + { + b = &cb->inherits ().base (); + continue; + } + + break; + } + + return *b; + } + else + return t; + } + private: template Edge* set_type (String const& type, XML::Element const& e, Node& node); private: + XML::PtrVector* dom_docs_; + struct Iterator { Iterator (Xerces::DOMElement* e) @@ -1518,6 +1583,10 @@ namespace XSDFrontend return file_stack_.top (); } + // Members with default/fixed values (needed for QName handling). + // + DefaultValues default_values_; + private: Boolean qualify_attribute_; Boolean qualify_element_; @@ -1696,6 +1765,12 @@ namespace XSDFrontend parse (Path const& tu) { valid_ = true; + schema_map_.clear (); + default_values_.clear (); + + XML::PtrVector dom_docs; + dom_docs_ = &dom_docs; + NamespaceMap cache; cache_ = &cache; @@ -1749,6 +1824,8 @@ namespace XSDFrontend s_ = cur_ = 0; } + dom_docs_->push_back (d); + // Second pass to resolve forward references to types, elements, // attributes and groups. // @@ -1778,7 +1855,7 @@ namespace XSDFrontend schema >> uses >> schema; schema >> schema_names >> ns >> ns_names; - Resolver resolver (*rs, valid_, *cache_); + Resolver resolver (*rs, valid_, *cache_, default_values_); struct AnonymousMember: Traversal::Attribute, Traversal::Element, @@ -1853,6 +1930,52 @@ namespace XSDFrontend schema.dispatch (*rs); } + // Resolve default/fixed values of QName type. + // + if (valid_) + { + for (DefaultValues::ConstIterator i (default_values_.begin ()), + e (default_values_.end ()); i != e; ++i) + { + SemanticGraph::Member& m (**i); + SemanticGraph::Type& t (m.type ()); + SemanticGraph::Context& c (m.context ()); + + if (ultimate_base (t).is_a ()) + { + String v (m.value ()); + Xerces::DOMElement* e (c.get ("dom-node")); + + try + { + // We have to try to resolve even the empty prefix since it can + // be assigned to a namespace (which takes precedence over names + // without a namespace). + // + String ns (XML::ns_name (e, XML::prefix (v))); + + if (m.fixed ()) + m.fixed (ns + L'#' + v); + else + m.default_ (ns + L'#' + v); + } + catch (XML::NoMapping const& ex) + { + if (!ex.prefix ().empty ()) + { + wcerr << m.file () << ":" << m.line () << ":" << m.column () + << ": error: unable to resolve namespace for prefix '" + << ex.prefix () << "'" << endl; + + valid_ = false; + } + } + } + + c.remove ("dom-node"); + } + } + if (!valid_) throw InvalidSchema (); @@ -1863,6 +1986,12 @@ namespace XSDFrontend parse (Paths const& paths) { valid_ = true; + schema_map_.clear (); + default_values_.clear (); + + XML::PtrVector dom_docs; + dom_docs_ = &dom_docs; + NamespaceMap cache; cache_ = &cache; @@ -1931,6 +2060,8 @@ namespace XSDFrontend cur_ = 0; + dom_docs_->push_back (d); + if (!valid_) break; } @@ -1966,7 +2097,7 @@ namespace XSDFrontend schema >> uses >> schema; schema >> schema_names >> ns >> ns_names; - Resolver resolver (*rs, valid_, *cache_); + Resolver resolver (*rs, valid_, *cache_, default_values_); struct AnonymousMember: Traversal::Attribute, Traversal::Element, @@ -2021,6 +2152,52 @@ namespace XSDFrontend schema.dispatch (*rs); } + // Resolve default/fixed values of QName type. + // + if (valid_) + { + for (DefaultValues::ConstIterator i (default_values_.begin ()), + e (default_values_.end ()); i != e; ++i) + { + SemanticGraph::Member& m (**i); + SemanticGraph::Type& t (m.type ()); + SemanticGraph::Context& c (m.context ()); + + if (ultimate_base (t).is_a ()) + { + String v (m.value ()); + Xerces::DOMElement* e (c.get ("dom-node")); + + try + { + // We have to try to resolve even the empty prefix since it can + // be assigned to a namespace (which takes precedence over names + // without a namespace). + // + String ns (XML::ns_name (e, XML::prefix (v))); + + if (m.fixed ()) + m.fixed (ns + L'#' + v); + else + m.default_ (ns + L'#' + v); + } + catch (XML::NoMapping const& ex) + { + if (!ex.prefix ().empty ()) + { + wcerr << m.file () << ":" << m.line () << ":" << m.column () + << ": error: unable to resolve namespace for prefix '" + << ex.prefix () << "'" << endl; + + valid_ = false; + } + } + } + + c.remove ("dom-node"); + } + } + if (!valid_) throw InvalidSchema (); @@ -2181,6 +2358,8 @@ namespace XSDFrontend cur_chameleon_ = old_cur_chameleon; cur_ = old_cur; + + dom_docs_->push_back (d); } } @@ -2309,6 +2488,8 @@ namespace XSDFrontend cur_chameleon_ = old_cur_chameleon; cur_ = old_cur; + + dom_docs_->push_back (d); } } @@ -3287,6 +3468,11 @@ namespace XSDFrontend else if (e.attribute_p ("default")) node.default_ (e.attribute ("default")); + if (node.default_ ()) + { + node.context ().set ("dom-node", e.dom_element ()); + default_values_.push_back (&node); + } if (global) { @@ -3407,6 +3593,12 @@ namespace XSDFrontend else if (e.attribute_p ("default")) node.default_ (e.attribute ("default")); + if (node.default_ ()) + { + node.context ().set ("dom-node", e.dom_element ()); + default_values_.push_back (&node); + } + // Parse annotation. // push (e); @@ -3450,6 +3642,14 @@ namespace XSDFrontend node.fixed (prot.value ()); else if (prot.default_ ()) node.default_ (prot.value ()); + + if (node.default_ ()) + { + node.context ().set ( + "dom-node", + prot.context ().get ("dom-node")); + default_values_.push_back (&node); + } } // Transfer annotation if the ref declaration hasn't defined its own. @@ -3646,6 +3846,11 @@ namespace XSDFrontend else if (a.attribute_p ("default")) node.default_ (a.attribute ("default")); + if (node.default_ ()) + { + node.context ().set ("dom-node", a.dom_element ()); + default_values_.push_back (&node); + } if (String type = a["type"]) { @@ -3733,6 +3938,11 @@ namespace XSDFrontend else if (a.attribute_p ("default")) node.default_ (a.attribute ("default")); + if (node.default_ ()) + { + node.context ().set ("dom-node", a.dom_element ()); + default_values_.push_back (&node); + } // Parse annotation. // @@ -3762,6 +3972,14 @@ namespace XSDFrontend node.fixed (prot.value ()); else if (prot.default_ ()) node.default_ (prot.value ()); + + if (node.default_ ()) + { + node.context ().set ( + "dom-node", + prot.context ().get ("dom-node")); + default_values_.push_back (&node); + } } // Transfer annotation if the ref declaration hasn't defined its own. diff --git a/xsd-frontend/xml.hxx b/xsd-frontend/xml.hxx index ed7d181..8c9b01c 100644 --- a/xsd-frontend/xml.hxx +++ b/xsd-frontend/xml.hxx @@ -6,13 +6,15 @@ #ifndef XSD_FRONTEND_XML_HXX #define XSD_FRONTEND_XML_HXX -#include -#include +#include #include #include -#include +#include + +#include +#include namespace XSDFrontend { @@ -172,7 +174,7 @@ namespace XSDFrontend ~XMLChString () { - Xerces::XMLString::release (&s_); + delete[] s_; } XMLCh const* @@ -339,7 +341,7 @@ namespace XSDFrontend // Throws NoMapping if there is no prefix-namespace association. // inline String - ns_name (Element const& e, String const& prefix) + ns_name (Xerces::DOMElement const* e, String const& prefix) { // 'xml' prefix requires special handling and Xerces folks refuse // to handle this in DOM so I have to do it myself. @@ -350,7 +352,7 @@ namespace XSDFrontend // 0 means "no prefix" to Xerces. // XMLCh const* xns ( - e.dom_element ()->lookupNamespaceURI ( + e->lookupNamespaceURI ( prefix.empty () ? 0 : XMLChString (prefix).c_str ())); if (xns == 0) @@ -362,8 +364,7 @@ namespace XSDFrontend class NoPrefix {}; inline String - ns_prefix (Element const& e, - String const& wns) + ns_prefix (Element const& e, String const& wns) { XMLChString ns (wns); @@ -403,7 +404,7 @@ namespace XSDFrontend try { - String ns (ns_name (e, prefix (n))); + String ns (ns_name (e.dom_element (), prefix (n))); return ns + L'#' + un; } catch (XML::NoMapping const&) @@ -527,6 +528,29 @@ namespace XSDFrontend private: X* x_; }; + + template + struct PtrVector: Cult::Containers::Vector + { + typedef Cult::Containers::Vector Base; + + ~PtrVector () + { + for (typename Base::Iterator i (this->begin ()), e (this->end ()); + i != e; ++i) + { + if (*i) + (*i)->release (); + } + } + + Void + push_back (AutoPtr& x) + { + Base::push_back (0); + this->back () = x.release (); + } + }; } } -- cgit v1.1