views:

40

answers:

3

I'll admit, I'm an XML newbie. I'm having trouble validating some xml against a schema. Here is the relevant part of my schema:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns="http://www.me.com/orpm/kpi/automation/report"
    targetNamespace="http://www.me.com/orpm/kpi/automation/report"&gt;
    <xs:attribute name="Pattern">
        <xs:simpleType>
            <xs:restriction base="xs:string">
                <xs:enumeration value="Exact"/>
                <xs:enumeration value="Replace"/>
                <xs:enumeration value="Regex"/>
            </xs:restriction>
        </xs:simpleType>
    </xs:attribute>
    <xs:complexType name="NameValue">
        <xs:all>
            <xs:element name="Value" type="xs:string"/>
        </xs:all>
        <xs:attribute ref="Pattern"/>
    </xs:complexType>
    <xs:element name="KpiReport">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="Name" type="NameValue"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

Here is the failed xml:

<?xml version="1.0"?>
<KpiReport xmlns="http://www.me.com/orpm/kpi/automation/report"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.me.com/orpm/kpi/automation/report filename.xsd">
    <Name Pattern="Exact">
        <Value>Test</Value>
    </Name>
</KpiReport>

It fails with this error:

Description: cvc-complex-type.2.4.a: Invalid content was found starting with element 'Name'. One of '{Name}' is expected.

I am lost on this. Please help.

+1  A: 

There are a couple of things going on, and a couple of possible solutions to your issue.

The solution that you can use will depend on whether you can change the XML, the XSD or both.

Below is some XML that passes your schema validation:

<?xml version="1.0"?> 
<ns0:KpiReport xmlns:ns0="http://www.me.com/orpm/kpi/automation/report" 
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 xsi:schemaLocation="http://www.me.com/orpm/kpi/automation/report filename.xsd"> 
    <Name ns0:Pattern="Exact"> 
        <Value>Test</Value> 
    </Name> 
</ns0:KpiReport>

The key difference is that in your xsd you have not defined the Name element within the http://www.me.com/orpm/kpi/automation/report namespace. I'm not entirely sure what is happening but think that having the Pattern attribute at the schema level has confused things. By assing the namespace prefix ns0: are telling the validator that KpiReport and Pattern are both in that namespace, but Name is not.

This solution may not fit, so the other option is to tweak your schema to accept your example XML. Below is a schema that works:

<?xml version="1.0" encoding="utf-16"?>
<xs:schema xmlns:b="http://schemas.microsoft.com/BizTalk/2003" xmlns="http://www.me.com/orpm/kpi/automation/report" targetNamespace="http://www.me.com/orpm/kpi/automation/report" xmlns:xs="http://www.w3.org/2001/XMLSchema"&gt;
  <xs:complexType name="NameValue">
    <xs:all>
      <xs:element form="qualified" name="Value" type="xs:string" />
    </xs:all>
    <xs:attribute name="Pattern">
      <xs:simpleType>
        <xs:restriction base="xs:string">
          <xs:enumeration value="Exact" />
          <xs:enumeration value="Replace" />
          <xs:enumeration value="Regex" />
        </xs:restriction>
      </xs:simpleType>
    </xs:attribute>
  </xs:complexType>
  <xs:element name="KpiReport">
    <xs:complexType>
      <xs:sequence>
        <xs:element form="qualified" name="Name" type="NameValue" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

Things to note are that the Pattern attribute is now moved into the NameValue complexType, and that Name and Value are now specified as form="qualified". Qualified means that these elements require namespace prefixes (in this case, the prefix is the default, or none).

I'm not 100% sure why this is required - my XSD knowledge is good enough to get to this point, but not know quite what is going on. I usually use tools to generate my schemas and then tweak until I've got things right.

Hopefully this helps you, or that someone with sharper XSD chops can fill in the gaps.

David Hall
Thanks. Moving the attribute inside the complextype worked like a charm. I've also made the form=qualified changes in my schema and things are working properly now. Thank you so much for taking the time to answer this question.
dmaruca
+2  A: 

david is correct, but the much better way for fixing this is to generally define locally defined elements as qualified in the schema. XSD has a terrible default there (which is the reason why your XSD did not work as intended), so virtually all tools generate an empty schema as this:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
</xs:schema>

this essentially does the same thing as the fix suggested by david, but does it by changing the XSD default, which is more robust.

the explanation of what exactly is going on might take a little too long to include here and is probably not of that much interest.

dret
@dret +1 one from me, and I'd love if you could add the explanation. As I said in my answer, while I'm OK with XSD, a lot is still a dark art and any further insight is very welcome.
David Hall
You're right, that is a terrible default. I generated that schema using the oXygen editor in combination with watching a Harvard lecture video online. I'll look for something in the options to set the qualified defaults. Thanks for the tip!
dmaruca
+2  A: 

ok, since david asked for it, here is the full explanation: element declarations in XSD can either be global or local. global declarations are on the level directly under xs:schema, local declarations are declarations inside other declarations. globally declared elements by definition always are defined in the targetNamespace of the schema (if there is one). local declarations, on the other hand, by default are in no namespace (specifically, not in the targetNamespace of the schema), unless you make them "qualified" by one of the two methods discussed already. the effect of elements declared without a namespace is that the document would have to look like this (using the "Name" and "Value" elements as elements without namespace-qualified names):

<?xml version="1.0"?> 
<KpiReport xmlns="http://www.me.com/orpm/kpi/automation/report"&gt; 
    <Name xmlns=""> 
        <Value>Test</Value> 
    </Name> 
</KpiReport>

this is not very pretty and definitely hard to use and understand, so this style of mixing qualified and unqualified element is never used (i've definitely never seen it).

dret
Thanks for that.
David Hall