xmerl XSD validation vs xmerl_xs:select and namespaces
Robert Raschke
rtrlists@REDACTED
Thu Jul 30 14:48:18 CEST 2009
Hi,
I'm a bit confused by the xmerl XSD validation. It seems that trying to
validate internal elements sometimes fails for reasons that are not clear to
me.
When using the purchase order example from
http://www.w3.org/TR/xmlschema-0/with the changes to make it use
namespaces:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:po="http://www.example.com/PO1"
targetNamespace="http://www.example.com/PO1"
elementFormDefault="qualified">
<xsd:element name="purchaseOrder" type="po:PurchaseOrderType"/>
<xsd:element name="comment" type="xsd:string"/>
<xsd:complexType name="PurchaseOrderType">
<xsd:sequence>
<xsd:element name="shipTo" type="po:USAddress"/>
<xsd:element name="billTo" type="po:USAddress"/>
<xsd:element ref="po:comment" minOccurs="0"/>
<xsd:element name="items" type="po:Items"/>
</xsd:sequence>
<xsd:attribute name="orderDate" type="xsd:date"/>
</xsd:complexType>
<xsd:complexType name="USAddress">
<xsd:sequence>
<xsd:element name="name" type="xsd:string"/>
<xsd:element name="street" type="xsd:string"/>
<xsd:element name="city" type="xsd:string"/>
<xsd:element name="state" type="xsd:string"/>
<xsd:element name="zip" type="xsd:decimal"/>
</xsd:sequence>
<xsd:attribute name="country" type="xsd:NMTOKEN"
fixed="US"/>
</xsd:complexType>
<xsd:complexType name="Items">
<xsd:sequence>
<xsd:element name="item" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="productName" type="xsd:string"/>
<xsd:element name="quantity">
<xsd:simpleType>
<xsd:restriction base="xsd:positiveInteger">
<xsd:maxExclusive value="100"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="USPrice" type="xsd:decimal"/>
<xsd:element ref="po:comment" minOccurs="0"/>
<xsd:element name="shipDate" type="xsd:date" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="partNum" type="po:SKU" use="required"/>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<!-- Stock Keeping Unit, a code for identifying products -->
<xsd:simpleType name="SKU">
<xsd:restriction base="xsd:string">
<xsd:pattern value="\d{3}-[A-Z]{2}"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
And a simple XML file that goes with this:
<?xml version="1.0"?>
<purchaseOrder xmlns="http://www.example.com/PO1"
orderDate="1999-10-20">
<shipTo country="US">
<name>Alice Smith</name>
<street>123 Maple Street</street>
<city>Mill Valley</city>
<state>CA</state>
<zip>90952</zip>
</shipTo>
<billTo country="US">
<name>Robert Smith</name>
<street>8 Oak Avenue</street>
<city>Old Town</city>
<state>PA</state>
<zip>95819</zip>
</billTo>
<comment>Hurry, my lawn is going wild</comment>
<items>
<item partNum="926-AA">
<productName>Baby Monitor</productName>
<quantity>1</quantity>
<USPrice>39.98</USPrice>
<shipDate>1999-05-21</shipDate>
</item>
</items>
</purchaseOrder>
Everything validates just fine:
Erlang (BEAM) emulator version 5.6.5 [smp:2] [async-threads:0]
Eshell V5.6.5 (abort with ^G)
1> rr(xmerl).
[xmerl_event,xmerl_fun_states,xmerl_scanner,xmlAttribute,
xmlComment,xmlContext,xmlDecl,xmlDocument,xmlElement,
xmlNamespace,xmlNode,xmlNsNode,xmlObj,xmlPI,xmlText]
2> {X01, _} = xmerl_scan:file("po.xml").
{#xmlElement{
name = purchaseOrder,expanded_name = purchaseOrder,
nsinfo = [],
namespace =
#xmlNamespace{
default = 'http://www.example.com/PO1',nodes = []},
parents = [],pos = 1,
attributes =
[#xmlAttribute{
name = xmlns,expanded_name = [],nsinfo = [],namespace = [],
parents = [],pos = 1,language = [],
value = "http://www.example.com/PO1",normalized = false},
#xmlAttribute{
name = orderDate,expanded_name = [],nsinfo = [],
namespace = [],parents = [],pos = 2,language = [],
value = "1999-10-20",normalized = false}],
content =
[#xmlText{
parents = [{purchaseOrder,1}],
pos = 1,language = [],value = "\n ",type = text},
#xmlElement{
name = shipTo,expanded_name = shipTo,nsinfo = [],
namespace =
#xmlNamespace{
default = 'http://www.example.com/PO1',nodes = []},
parents = [{purchaseOrder,1}],
pos = 2,
attributes =
[#xmlAttribute{
name = country,expanded_name = [],nsinfo = [],
namespace = [],parents = [],pos = 1,language =
[],...}],
content =
[#xmlText{
parents = [{shipTo,2},{purchaseOrder,1}],
pos = 1,language = [],value = "\n ",type = text},
#xmlElement{
name = name,expanded_name = name,nsinfo = [],
namespace = #xmlNamespace{...},
parents = [...],...},
#xmlText{
parents = [{shipTo,2},{purchaseOrder,...}],
pos = 3,language = [],
value = [...],...},
#xmlElement{
name = street,expanded_name = street,nsinfo =
[],...},
#xmlText{parents = [{...}|...],pos = 5,...},
#xmlElement{name = city,...},
#xmlText{...},
{...}|...],
language = [],xmlbase = ".",elementdef = undeclared},
#xmlText{
parents = [{purchaseOrder,1}],
pos = 3,language = [],value = "\n ",type = text},
#xmlElement{
name = billTo,expanded_name = billTo,nsinfo = [],
namespace =
#xmlNamespace{
default = 'http://www.example.com/PO1',nodes = []},
parents = [{purchaseOrder,1}],
pos = 4,
attributes =
[#xmlAttribute{
name = country,expanded_name = [],nsinfo = [],
namespace = [],parents = [],...}],
content =
[#xmlText{
parents = [{billTo,4},{purchaseOrder,...}],
pos = 1,language = [],
value = [...],...},
#xmlElement{
name = name,expanded_name = name,nsinfo = [],...},
#xmlText{parents = [{...}|...],pos = 3,...},
#xmlElement{name = street,...},
#xmlText{...},
{...}|...],
language = [],xmlbase = ".",elementdef = undeclared},
#xmlText{
parents = [{purchaseOrder,1}],
pos = 5,language = [],value = "\n ",type = text},
#xmlElement{
name = comment,expanded_name = comment,nsinfo = [],
namespace =
#xmlNamespace{
default = 'http://www.example.com/PO1',nodes = []},
parents = [{purchaseOrder,1}],
pos = 6,attributes = [],
content = [#xmlText{parents = [{...}|...],pos = 1,...}],
language = [],xmlbase = ".",elementdef = undeclared},
#xmlText{
parents = [{purchaseOrder,1}],
pos = 7,language = [],value = "\n ",type = text},
#xmlElement{
name = items,expanded_name = items,nsinfo = [],
namespace =
#xmlNamespace{
default = 'http://www.example.com/PO1',nodes = []},
parents = [{purchaseOrder,1}],
pos = 8,attributes = [],
content = [#xmlText{...},{...}|...],
language = [],
xmlbase = [...],...},
#xmlText{
parents = [{purchaseOrder,1}],
pos = 9,language = [],value = "\n",type = text}],
language = [],xmlbase = ".",elementdef = undeclared},
[]}
3> xmerl_xsd:process_validate("po.xsd", X01).
{#xmlElement{
name = purchaseOrder,expanded_name = purchaseOrder,
nsinfo = [],
namespace =
#xmlNamespace{
default = 'http://www.example.com/PO1',nodes = []},
parents = [],pos = 1,
attributes =
[#xmlAttribute{
name = xmlns,expanded_name = [],nsinfo = [],namespace = [],
parents = [],pos = 1,language = [],
value = "http://www.example.com/PO1",normalized = false},
#xmlAttribute{
name = orderDate,expanded_name = [],nsinfo = [],
namespace = [],parents = [],pos = 2,language = [],
value = "1999-10-20",normalized = false}],
content =
[#xmlText{
parents = [{purchaseOrder,1}],
pos = 1,language = [],value = "\n ",type = text},
#xmlElement{
name = shipTo,expanded_name = shipTo,nsinfo = [],
namespace =
#xmlNamespace{
default = 'http://www.example.com/PO1',nodes = []},
parents = [{purchaseOrder,1}],
pos = 2,
attributes =
[#xmlAttribute{
name = country,expanded_name = [],nsinfo = [],
namespace = [],parents = [],pos = 1,language =
[],...}],
content =
[#xmlText{
parents = [{shipTo,2},{purchaseOrder,1}],
pos = 1,language = [],value = "\n ",type = text},
#xmlElement{
name = name,expanded_name = name,nsinfo = [],
namespace = #xmlNamespace{...},
parents = [...],...},
#xmlText{
parents = [{shipTo,2},{purchaseOrder,...}],
pos = 3,language = [],
value = [...],...},
#xmlElement{
name = street,expanded_name = street,nsinfo =
[],...},
#xmlText{parents = [{...}|...],pos = 5,...},
#xmlElement{name = city,...},
#xmlText{...},
{...}|...],
language = [],xmlbase = ".",elementdef = undeclared},
#xmlText{
parents = [{purchaseOrder,1}],
pos = 3,language = [],value = "\n ",type = text},
#xmlElement{
name = billTo,expanded_name = billTo,nsinfo = [],
namespace =
#xmlNamespace{
default = 'http://www.example.com/PO1',nodes = []},
parents = [{purchaseOrder,1}],
pos = 4,
attributes =
[#xmlAttribute{
name = country,expanded_name = [],nsinfo = [],
namespace = [],parents = [],...}],
content =
[#xmlText{
parents = [{billTo,4},{purchaseOrder,...}],
pos = 1,language = [],
value = [...],...},
#xmlElement{
name = name,expanded_name = name,nsinfo = [],...},
#xmlText{parents = [{...}|...],pos = 3,...},
#xmlElement{name = street,...},
#xmlText{...},
{...}|...],
language = [],xmlbase = ".",elementdef = undeclared},
#xmlText{
parents = [{purchaseOrder,1}],
pos = 5,language = [],value = "\n ",type = text},
#xmlElement{
name = comment,expanded_name = comment,nsinfo = [],
namespace =
#xmlNamespace{
default = 'http://www.example.com/PO1',nodes = []},
parents = [{purchaseOrder,1}],
pos = 6,attributes = [],
content = [#xmlText{parents = [{...}|...],pos = 1,...}],
language = [],xmlbase = ".",elementdef = undeclared},
#xmlText{
parents = [{purchaseOrder,1}],
pos = 7,language = [],value = "\n ",type = text},
#xmlElement{
name = items,expanded_name = items,nsinfo = [],
namespace =
#xmlNamespace{
default = 'http://www.example.com/PO1',nodes = []},
parents = [{purchaseOrder,1}],
pos = 8,attributes = [],
content = [#xmlText{...},{...}|...],
language = [],
xmlbase = [...],...},
#xmlText{
parents = [{purchaseOrder,1}],
pos = 9,language = [],value = "\n",type = text}],
language = [],xmlbase = ".",elementdef = undeclared},
{xsd_state,"po.xsd",
[138828883239791335015413488673396043202],
false,".",[],[],[],qualified,unqualified,undefined,
'http://www.example.com/PO1',
[{"po",'http://www.example.com/PO1'},
{"xsd",'http://www.w3.org/2001/XMLSchema'},
{"xml",'http://www.w3.org/XML/1998/namespace'}],
[{'http://www.example.com/PO1',
[{"xsd",'http://www.w3.org/2001/XMLSchema'},
{"po",'http://www.example.com/PO1'}]}],
[{"#this#","po.xsd",'http://www.example.com/PO1'},
{"xml",[],'http://www.w3.org/XML/1998/namespace'}],
28685,false,false,[],[],#Fun<xmerl_xsd.0.57810061>,[],0,[],
[],[],[],...}}
But if I edit the XML to have some prefix namespaced elements around the
outside:
<?xml version="1.0"?>
<p:foo xmlns:p="foobar"><p:bar>
<purchaseOrder xmlns="http://www.example.com/PO1"
orderDate="1999-10-20">
<shipTo country="US">
<name>Alice Smith</name>
<street>123 Maple Street</street>
<city>Mill Valley</city>
<state>CA</state>
<zip>90952</zip>
</shipTo>
<billTo country="US">
<name>Robert Smith</name>
<street>8 Oak Avenue</street>
<city>Old Town</city>
<state>PA</state>
<zip>95819</zip>
</billTo>
<comment>Hurry, my lawn is going wild</comment>
<items>
<item partNum="926-AA">
<productName>Baby Monitor</productName>
<quantity>1</quantity>
<USPrice>39.98</USPrice>
<shipDate>1999-05-21</shipDate>
</item>
</items>
</purchaseOrder>
</p:bar></p:foo>
And then I retrieve the default namespaced purchaseOrder element using
xmerl_xs:select/2, then the XSD validation fails:
4> {X02, _} = xmerl_scan:file("po.xml").
{#xmlElement{
name = 'p:foo',expanded_name = 'p:foo',
nsinfo = {"p","foo"},
namespace =
#xmlNamespace{default = [],nodes = [{"p",foobar}]},
parents = [],pos = 1,
attributes =
[#xmlAttribute{
name = 'xmlns:p',expanded_name = [],nsinfo = [],
namespace = {"xmlns","p"},
parents = [],pos = 1,language = [],value = "foobar",
normalized = false}],
content =
[#xmlElement{
name = 'p:bar',expanded_name = 'p:bar',
nsinfo = {"p","bar"},
namespace =
#xmlNamespace{default = [],nodes = [{"p",foobar}]},
parents = [{'p:foo',1}],
pos = 1,attributes = [],
content =
[#xmlText{
parents = [{'p:bar',1},{'p:foo',1}],
pos = 1,language = [],value = "\n",type = text},
#xmlElement{
name = purchaseOrder,expanded_name = purchaseOrder,
nsinfo = [],
namespace =
#xmlNamespace{
default = 'http://www.example.com/PO1',...},
parents = [{...}|...],
pos = 2,...},
#xmlText{
parents = [{'p:bar',1},{'p:foo',1}],
pos = 3,language = [],value = "\n",type = text}],
language = [],xmlbase = ".",elementdef = undeclared}],
language = [],xmlbase = ".",elementdef = undeclared},
[]}
5> [X03] = xmerl_xs:select("/p:foo/p:bar/*", X02).
[#xmlElement{
name = purchaseOrder,expanded_name = purchaseOrder,
nsinfo = [],
namespace =
#xmlNamespace{
default = 'http://www.example.com/PO1',
nodes = [{"p",foobar}]},
parents = [{'p:bar',1},{'p:foo',1}],
pos = 2,
attributes =
[#xmlAttribute{
name = xmlns,expanded_name = [],nsinfo = [],namespace = [],
parents = [],pos = 1,language = [],
value = "http://www.example.com/PO1",normalized = false},
#xmlAttribute{
name = orderDate,expanded_name = [],nsinfo = [],
namespace = [],parents = [],pos = 2,language = [],
value = "1999-10-20",normalized = false}],
content =
[#xmlText{
parents = [{purchaseOrder,2},{'p:bar',1},{'p:foo',1}],
pos = 1,language = [],value = "\n ",type = text},
#xmlElement{
name = shipTo,expanded_name = shipTo,nsinfo = [],
namespace =
#xmlNamespace{
default = 'http://www.example.com/PO1',
nodes = [{"p",foobar}]},
parents = [{purchaseOrder,2},{'p:bar',1},{'p:foo',1}],
pos = 2,
attributes =
[#xmlAttribute{
name = country,expanded_name = [],nsinfo = [],
namespace = [],parents = [],pos = 1,language =
[],...}],
content =
[#xmlText{
parents =
[{shipTo,2},
{purchaseOrder,2},
{'p:bar',1},
{'p:foo',...}],
pos = 1,language = [],value = "\n ",type = text},
#xmlElement{
name = name,expanded_name = name,nsinfo = [],
namespace = #xmlNamespace{...},
parents = [...],...},
#xmlText{
parents = [{shipTo,2},{purchaseOrder,...},{...}|...],
pos = 3,language = [],
value = [...],...},
#xmlElement{
name = street,expanded_name = street,nsinfo =
[],...},
#xmlText{parents = [{...}|...],pos = 5,...},
#xmlElement{name = city,...},
#xmlText{...},
{...}|...],
language = [],xmlbase = ".",elementdef = undeclared},
#xmlText{
parents = [{purchaseOrder,2},{'p:bar',1},{'p:foo',1}],
pos = 3,language = [],value = "\n ",type = text},
#xmlElement{
name = billTo,expanded_name = billTo,nsinfo = [],
namespace =
#xmlNamespace{
default = 'http://www.example.com/PO1',
nodes = [{"p",foobar}]},
parents = [{purchaseOrder,2},{'p:bar',1},{'p:foo',1}],
pos = 4,
attributes =
[#xmlAttribute{
name = country,expanded_name = [],nsinfo = [],
namespace = [],parents = [],...}],
content =
[#xmlText{
parents = [{billTo,4},{purchaseOrder,...},{...}|...],
pos = 1,language = [],
value = [...],...},
#xmlElement{
name = name,expanded_name = name,nsinfo = [],...},
#xmlText{parents = [{...}|...],pos = 3,...},
#xmlElement{name = street,...},
#xmlText{...},
{...}|...],
language = [],xmlbase = ".",elementdef = undeclared},
#xmlText{
parents = [{purchaseOrder,2},{'p:bar',1},{'p:foo',1}],
pos = 5,language = [],value = "\n ",type = text},
#xmlElement{
name = comment,expanded_name = comment,nsinfo = [],
namespace =
#xmlNamespace{
default = 'http://www.example.com/PO1',
nodes = [{"p",foobar}]},
parents = [{purchaseOrder,2},{'p:bar',1},{'p:foo',1}],
pos = 6,attributes = [],
content = [#xmlText{parents = [{...}|...],pos = 1,...}],
language = [],xmlbase = ".",elementdef = undeclared},
#xmlText{
parents = [{purchaseOrder,2},{'p:bar',1},{'p:foo',1}],
pos = 7,language = [],value = "\n ",type = text},
#xmlElement{
name = items,expanded_name = items,nsinfo = [],
namespace =
#xmlNamespace{
default = 'http://www.example.com/PO1',
nodes = [{"p",foobar}]},
parents = [{purchaseOrder,2},{'p:bar',1},{'p:foo',1}],
pos = 8,attributes = [],
content = [#xmlText{...},{...}|...],
language = [],
xmlbase = [...],...},
#xmlText{
parents = [{purchaseOrder,2},{'p:bar',1},{'p:foo',1}],
pos = 9,language = [],value = "\n",type = text}],
language = [],xmlbase = ".",elementdef = undeclared}]
6> xmerl_xsd:process_validate("po.xsd", X03).
{error,
[{"p:foo[1]/p:bar[1]",xmerl_xsd,
{element_not_in_schema,
[purchaseOrder,
{purchaseOrder,[],foobar},
{schema,undefined,undefined,undefined,[],[],undefined,
[]}]}}]}
Does anyone know why this might be the case?
Thanks for any info,
Robby
More information about the erlang-questions
mailing list