aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2010-01-08 14:04:58 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2010-01-08 14:04:58 +0200
commit448760cbdb8f1ee1f3eb3559c7b05e7a61e37a88 (patch)
tree02c404a950281d7af209ee3f786e8abe13d4565f
parent4bbabb3f78ab943c1fecbed08b1920db9609bc34 (diff)
Resolve namespace for default/fixed values of QName type
-rw-r--r--NEWS5
-rw-r--r--tests/dump/driver.cxx29
-rw-r--r--tests/schema/default/makefile35
-rw-r--r--tests/schema/default/test-000.std28
-rw-r--r--tests/schema/default/test-000.xsd23
-rw-r--r--tests/schema/default/test-001.std15
-rw-r--r--tests/schema/default/test-001.xsd11
-rw-r--r--tests/schema/makefile2
-rw-r--r--xsd-frontend/parser.cxx228
-rw-r--r--xsd-frontend/xml.hxx42
10 files changed, 402 insertions, 16 deletions
diff --git a/NEWS b/NEWS
index 6eeef9f..a8e8dae 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,8 @@
+Version 1.17.0
+
+ * Add support for resolving default/fixed values of QName type. Now
+ the qualified value is represented in the <namespace>#<qname> form.
+
Version 1.16.0
* New transformation: simplifier. It simplifies the schema graph
diff --git a/tests/dump/driver.cxx b/tests/dump/driver.cxx
index cca6249..d9917d3 100644
--- a/tests/dump/driver.cxx
+++ b/tests/dump/driver.cxx
@@ -203,6 +203,11 @@ namespace
wcout << ind << (a.optional () ? "optional" : "required")
<< " attribute " << a.name ();
+ if (a.fixed ())
+ wcout << "==" << a.value ();
+ else if (a.default_ ())
+ wcout << "=" << a.value ();
+
SemanticGraph::Type& t (a.type ());
if (t.named ())
@@ -241,6 +246,11 @@ namespace
{
wcout << "element " << e.name ();
+ if (e.fixed ())
+ wcout << "==" << e.value ();
+ else if (e.default_ ())
+ wcout << "=" << e.value ();
+
SemanticGraph::Type& t (e.type ());
if (t.named ())
@@ -268,7 +278,14 @@ namespace
wcout << ind << "<" << e.annotation ().documentation () << ">"
<< endl;
- wcout << ind << "element " << e.name () << endl;
+ wcout << ind << "element " << e.name ();
+
+ if (e.fixed ())
+ wcout << "==" << e.value ();
+ else if (e.default_ ())
+ wcout << "=" << e.value ();
+
+ wcout << endl;
}
};
@@ -343,6 +360,11 @@ namespace
wcout << ind << "attribute " << a.name ();
+ if (a.fixed ())
+ wcout << "==" << a.value ();
+ else if (a.default_ ())
+ wcout << "=" << a.value ();
+
SemanticGraph::Type& t (a.type ());
if (t.named ())
@@ -372,6 +394,11 @@ namespace
wcout << ind << "element " << e.name ();
+ if (e.fixed ())
+ wcout << "==" << e.value ();
+ else if (e.default_ ())
+ wcout << "=" << e.value ();
+
SemanticGraph::Type& t (e.type ());
if (t.named ())
diff --git a/tests/schema/default/makefile b/tests/schema/default/makefile
new file mode 100644
index 0000000..dbb5fa9
--- /dev/null
+++ b/tests/schema/default/makefile
@@ -0,0 +1,35 @@
+# file : tests/schema/default/makefile
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# copyright : Copyright (c) 2006-2010 Code Synthesis Tools CC
+# license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../../../build/bootstrap.make
+
+tests := 000 001
+
+driver := $(out_root)/tests/dump/driver
+test := $(out_base)/.test
+clean := $(out_base)/.clean
+
+# Convenience alias for default target.
+#
+$(out_base)/: $(driver)
+
+# Test.
+#
+test_targets := $(addprefix $(out_base)/.test-,$(tests))
+
+$(test): $(test_targets)
+$(test_targets): driver := $(driver)
+
+.PHONY: $(out_base)/.test-%
+$(out_base)/.test-%: $(driver) $(src_base)/test-%.xsd $(src_base)/test-%.std
+ $(call message,test $(out_base)/$*,$(driver) --anonymous $(src_base)/test-$*.xsd | diff -u $(src_base)/test-$*.std -)
+
+# Clean.
+#
+$(clean):
+
+# Dependencies.
+#
+$(call import,$(src_root)/tests/dump/makefile)
diff --git a/tests/schema/default/test-000.std b/tests/schema/default/test-000.std
new file mode 100644
index 0000000..efa1140
--- /dev/null
+++ b/tests/schema/default/test-000.std
@@ -0,0 +1,28 @@
+primary
+{
+ namespace test
+ {
+ complex type
+ {
+ element e1=123
+ element e2==456
+ element e3=unqual
+ element e4==test#t:foo
+ element e5=foo#x:bar
+ optional attribute a1=123 http://www.w3.org/2001/XMLSchema#int
+ optional attribute a2==456 http://www.w3.org/2001/XMLSchema#int
+ optional attribute a3=foo#x:bar test#qname
+ [1, 1] sequence
+ {
+ [1, 1] element e1=123 http://www.w3.org/2001/XMLSchema#int
+ [1, 1] element e2==456 http://www.w3.org/2001/XMLSchema#int
+ [1, 1] element e3=unqual http://www.w3.org/2001/XMLSchema#QName
+ [1, 1] element e4==test#t:foo http://www.w3.org/2001/XMLSchema#QName
+ [1, 1] element e5=foo#x:bar http://www.w3.org/2001/XMLSchema#QName
+ }
+ }
+ complex qname: http://www.w3.org/2001/XMLSchema#QName
+ {
+ }
+ }
+}
diff --git a/tests/schema/default/test-000.xsd b/tests/schema/default/test-000.xsd
new file mode 100644
index 0000000..bfaedc5
--- /dev/null
+++ b/tests/schema/default/test-000.xsd
@@ -0,0 +1,23 @@
+<?xml version="1.0"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:t="test" xmlns:x="foo" targetNamespace="test">
+
+ <xs:complexType name="type">
+ <xs:sequence>
+ <xs:element name="e1" type="xs:int" default="123"/>
+ <xs:element name="e2" type="xs:int" fixed="456"/>
+
+ <xs:element name="e3" type="xs:QName" default="unqual"/>
+ <xs:element name="e4" type="xs:QName" fixed="t:foo"/>
+ <xs:element name="e5" type="xs:QName" default="x:bar"/>
+ </xs:sequence>
+ <xs:attribute name="a1" type="xs:int" default="123"/>
+ <xs:attribute name="a2" type="xs:int" fixed="456"/>
+
+ <xs:attribute name="a3" type="t:qname" default="x:bar"/>
+ </xs:complexType>
+
+ <xs:simpleType name="qname">
+ <xs:restriction base="xs:QName"/>
+ </xs:simpleType>
+
+</xs:schema>
diff --git a/tests/schema/default/test-001.std b/tests/schema/default/test-001.std
new file mode 100644
index 0000000..1b84a07
--- /dev/null
+++ b/tests/schema/default/test-001.std
@@ -0,0 +1,15 @@
+primary
+{
+ namespace test
+ {
+ complex type
+ {
+ element e=foo#unqual
+ optional attribute a=foo#unqual http://www.w3.org/2001/XMLSchema#QName
+ [1, 1] sequence
+ {
+ [1, 1] element e=foo#unqual http://www.w3.org/2001/XMLSchema#QName
+ }
+ }
+ }
+}
diff --git a/tests/schema/default/test-001.xsd b/tests/schema/default/test-001.xsd
new file mode 100644
index 0000000..5ee0507
--- /dev/null
+++ b/tests/schema/default/test-001.xsd
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:t="test" xmlns="foo" targetNamespace="test">
+
+ <xs:complexType name="type">
+ <xs:sequence>
+ <xs:element name="e" type="xs:QName" default="unqual"/>
+ </xs:sequence>
+ <xs:attribute name="a" type="xs:QName" default="unqual"/>
+ </xs:complexType>
+
+</xs:schema>
diff --git a/tests/schema/makefile b/tests/schema/makefile
index c422973..9b69ea7 100644
--- a/tests/schema/makefile
+++ b/tests/schema/makefile
@@ -5,7 +5,7 @@
include $(dir $(lastword $(MAKEFILE_LIST)))../../build/bootstrap.make
-tests := annotation anonymous attribute-group element-group
+tests := annotation anonymous attribute-group element-group default
default := $(out_base)/
test := $(out_base)/.test
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 <cult/containers/map.hxx>
#include <cult/containers/stack.hxx>
+#include <cult/containers/vector.hxx>
#include <cult/rtti/type-id.hxx>
//@@ Do i need this?
@@ -120,6 +121,7 @@ namespace XSDFrontend
typedef Cult::Containers::Map<String, CacheNodes> NodeMap;
typedef Cult::Containers::Map<String, NodeMap> NamespaceMap;
+ typedef Cult::Containers::Vector<SemanticGraph::Member*> DefaultValues;
template <typename X>
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<Xerces::DOMElement*> ("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<Xerces::DOMElement*> ("dom-node"));
+ default_values_.push_back (&copy);
+ }
+
// 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<Xerces::DOMElement*> ("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<Complex*> (&t);
+
+ if (c != 0 && c->inherits_p ())
+ {
+ Type* b (&c->inherits ().base ());
+
+ while (true)
+ {
+ Complex* cb (dynamic_cast<Complex*> (b));
+
+ if (cb != 0 && cb->inherits_p ())
+ {
+ b = &cb->inherits ().base ();
+ continue;
+ }
+
+ break;
+ }
+
+ return *b;
+ }
+ else
+ return t;
+ }
+
private:
template <typename Edge, typename Node>
Edge*
set_type (String const& type, XML::Element const& e, Node& node);
private:
+ XML::PtrVector<Xerces::DOMDocument>* 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<Xerces::DOMDocument> 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<SemanticGraph::Fundamental::QName> ())
+ {
+ String v (m.value ());
+ Xerces::DOMElement* e (c.get<Xerces::DOMElement*> ("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<Xerces::DOMDocument> 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<SemanticGraph::Fundamental::QName> ())
+ {
+ String v (m.value ());
+ Xerces::DOMElement* e (c.get<Xerces::DOMElement*> ("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<Xerces::DOMElement*> ("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<Xerces::DOMElement*> ("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 <xsd-frontend/types.hxx>
-#include <xsd-frontend/schema-dom-parser.hxx>
+#include <ostream>
#include <xercesc/dom/DOM.hpp>
#include <xercesc/util/XMLString.hpp>
-#include <ostream>
+#include <cult/containers/vector.hxx>
+
+#include <xsd-frontend/types.hxx>
+#include <xsd-frontend/schema-dom-parser.hxx>
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 <typename X>
+ struct PtrVector: Cult::Containers::Vector<X*>
+ {
+ typedef Cult::Containers::Vector<X*> Base;
+
+ ~PtrVector ()
+ {
+ for (typename Base::Iterator i (this->begin ()), e (this->end ());
+ i != e; ++i)
+ {
+ if (*i)
+ (*i)->release ();
+ }
+ }
+
+ Void
+ push_back (AutoPtr<X>& x)
+ {
+ Base::push_back (0);
+ this->back () = x.release ();
+ }
+ };
}
}