XML Schema 1.0 - qualified versus unqualified: what specifically changes in a valid instance? - validation

Say I have a valid XML instance file ("1") that contains only elements in the targetNamespace of its schema (Schema "A"). The instance is valid per this schema. Instance 1 has the correct namespace declaration for its schema on its (1's) root node, and nowhere else.
Now I take the same instance 1 and try to validate it against Schema "B".
B is identical to A except I changed elementFormDefault="unqualified" to elementFormDefault="qualified".
I am seeing 1 failing to validate against B. Why? What do I need to change in 1 (producing instance "2") to make it valid again against B?
Is the "qualified" flavor of an XML schema just for instances with an explicit namespace prefix on every single element?
Example schemas: All based on a minimal XML structure for communicating some data structures like file/record/info1. Unfortunately these seem to behave differently again from my real-world examples (which are too big to post here).
A: UNqualified schema
<?xml version="1.0" encoding="UTF-8"?>
<!-- The UNqualified version -->
<xs:schema elementFormDefault="unqualified" targetNamespace="http://example.com/xsd-prefixes-test"
xmlns:test="http://example.com/xsd-prefixes-test" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="file">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" ref="test:record" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="record">
<xs:complexType>
<xs:sequence>
<xs:element ref="test:info1" />
<xs:element ref="test:info2" />
</xs:sequence>
<xs:attribute name="id" type="xs:integer" use="required" />
<xs:attribute name="status" type="xs:NCName" use="required" />
</xs:complexType>
</xs:element>
<xs:element name="info1">
<xs:complexType />
</xs:element>
<xs:element name="info2">
<xs:complexType />
</xs:element>
</xs:schema>
B: QUALIFIED schema
<?xml version="1.0" encoding="UTF-8"?>
<!-- The QUALIFIED version -->
<xs:schema elementFormDefault="qualified" targetNamespace="http://example.com/xsd-prefixes-test"
xmlns:test="http://example.com/xsd-prefixes-test" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="file">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" ref="test:record" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="record">
<xs:complexType>
<xs:sequence>
<xs:element ref="test:info1" />
<xs:element ref="test:info2" />
</xs:sequence>
<xs:attribute name="id" type="xs:integer" use="required" />
<xs:attribute name="status" type="xs:NCName" use="required" />
</xs:complexType>
</xs:element>
<xs:element name="info1">
<xs:complexType />
</xs:element>
<xs:element name="info2">
<xs:complexType />
</xs:element>
</xs:schema>
Example schema instances:
Instance 1 - prefixes for the targetNamespace on all elements; validates against both schemas
<?xml version="1.0" encoding="UTF-8"?>
<!-- ALL prefixes -->
<test:file xmlns:test="http://example.com/xsd-prefixes-test"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://example.com/xsd-prefixes-test xsd-prefixes-test_qualified.xsd">
<!-- validates against xsd-prefixes-test_UNqualified.xsd AND xsd-prefixes-test_qualified.xsd -->
<test:record id="1" status="ok">
<test:info1 />
<test:info2 />
<!-- etc... -->
</test:record>
<test:record id="1" status="ok">
<test:info1 />
<test:info2 />
<!-- etc... -->
</test:record>
<test:record id="1" status="duplicate_deprecated">
<test:info1 />
<test:info2 />
<!-- etc... -->
</test:record>
</test:file>
Instance 2: - no namespace prefixes anywhere but still validates against A and B!
<?xml version="1.0" encoding="UTF-8"?>
<!-- NO prefixes anywhere -->
<file xmlns="http://example.com/xsd-prefixes-test" xmlns:test="http://example.com/xsd-prefixes-test"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://example.com/xsd-prefixes-test xsd-prefixes-test_qualified.xsd">
<!-- validates against BOTH xsd-prefixes-test_UNqualified.xsd AND xsd-prefixes-test_qualified.xsd -->
<record id="1" status="ok">
<info1 />
<info2 />
<!-- etc... -->
</record>
<record id="1" status="ok">
<info1 />
<info2 />
<!-- etc... -->
</record>
<record id="1" status="duplicate_deprecated">
<info1 />
<info2 />
<!-- etc... -->
</record>
</file>
Instance 3 - does not validate against either A or B - why not?
<?xml version="1.0" encoding="UTF-8"?>
<!-- NO prefixes anywhere -->
<test:file xmlns:test="http://example.com/xsd-prefixes-test"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://example.com/xsd-prefixes-test xsd-prefixes-test_qualified.xsd">
<!-- validates against NEITHER xsd-prefixes-test_UNqualified.xsd NOR xsd-prefixes-test_qualified.xsd -->
<record id="1" status="ok">
<info1 />
<info2 />
<!-- etc... -->
</record>
<record id="1" status="ok">
<info1 />
<info2 />
<!-- etc... -->
</record>
<record id="1" status="duplicate_deprecated">
<info1 />
<info2 />
<!-- etc... -->
</record>
</test:file>
Error messages (same with both schemas A and B):
Instance 3 - cvc-complex-type.2.4.a: Invalid content was found starting with element 'record'. One of '{"http://example.com/xsd-prefixes-test":record}' is expected.
I am seeing this error or very similar with instance files along the pattern of both 1 and 2, when used with the schema of the "opposite" flavor (an instance with prefixes against a schema with unqualified).
Conversely I am seeing instances of style 3 that do validate against the qualified type schema.
Is there a dependency on what language/parser/validation engine is used?

Related

XSD for auto closing tag in complexType

I have this in my XML file:
<rooms>
<room id="1" beds="1" windows="0"/>
<room id="2" beds="2" windows="0"/>
</rooms>
And this in my XSD file:
<xs:complexType name="Rooms">
<xs:sequence>
<xs:element name="room" type="Room"/>
</xs:sequence>
<xs:attribute name="count" type="xs:integer"/>
</xs:complexType>
<xs:complexType name="Room">
<xs:attribute name="id" type="xs:integer"/>
<xs:attribute name="beds" type="xs:integer"/>
<xs:attribute name="windows" type="xs:integer"/>
</xs:complexType>
But I got this error : Element 'room': This element is not expected.
When I put <room id="1" beds="1" windows="0"></room> I don't have the error anymore and if I have only one room I don't have the error, so it's basically because of the auto closing tag.
How can I fix this?
Try specifying values for minOccurs and maxOccurs to your room element inside the sequence. I think the default expected number of occurrences is 1. Something like:
<xs:sequence>
<xs:element name="room" type="Room" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>

XSD key not in root element and complex keys

I searched for this, but can't find solution to my problem, so please don't trash this question.
We have a service with very complex XML configuration which is described by XSD. There are many rules that must be obeyed for things to run smoothly. XSD describes structure of configuration, but not the rules, which we must do now. After creating some global rules we have to do some more complex now and we encountered a problem. It seams like validator only uses key/keyref/unique from root element. I've created small XSD and XML file to illustrate that:
XSD:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema targetNamespace="http://test.org/XMLSchema.xsd"
elementFormDefault="qualified"
xmlns="http://test.org/XMLSchema.xsd"
xmlns:t="http://test.org/XMLSchema.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Orders" type="t:OrdersList">
<xs:key name="OrderNo">
<xs:selector xpath="./t:Order" />
<xs:field xpath="#Number" />
</xs:key>
</xs:element>
<xs:complexType name="OrdersList">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="Order" nillable="false" type="t:Order" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="Order">
<xs:sequence>
<xs:element minOccurs="1" maxOccurs="1" name="Lines" nillable="false" type="t:OrdersLinesList" />
</xs:sequence>
<xs:attribute name="Number" use="optional" type="xs:string" />
<xs:attribute name="ClientId" use="optional" type="xs:int" />
</xs:complexType>
<xs:complexType name="OrdersLinesList">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="Line" nillable="false" type="t:OrderLine">
<!-- THE PROBLEM -->
<xs:key name="LineNoKey">
<xs:selector xpath="./t:Line" />
<xs:field xpath="#LineNumber" />
</xs:key>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="OrderLine">
<xs:attribute name="LineNumber" use="optional" type="xs:string" />
<xs:attribute name="ProductId" use="optional" type="xs:int" />
<xs:attribute name="Amount" use="optional" type="xs:decimal" />
</xs:complexType>
</xs:schema>
XML:
<?xml version="1.0" encoding="utf-8"?>
<Orders xmlns="http://test.org/XMLSchema.xsd">
<Order Number="0001/5/13" ClientId="123">
<Lines>
<Line LineNumber="1" ProductId="123" Amount="4" />
<Line LineNumber="2" ProductId="124" Amount="4" />
</Lines>
</Order>
<Order Number="0002/5/13" ClientId="123">
<Lines>
<Line LineNumber="1" ProductId="123" Amount="4" />
<!-- Duplicate number - it DOES validate as expected. -->
<Line LineNumber="1" ProductId="124" Amount="4" />
</Lines>
</Order>
<!-- Duplicate number - it doesn't validate as expected. -->
<Order Number="0002/5/13" ClientId="123">
<Lines>
<Line LineNumber="1" ProductId="123" Amount="4" />
<Line LineNumber="2" ProductId="124" Amount="4" />
</Lines>
</Order>
</Orders>
I have a few questions which I can't find any sensible answer:
How to solve the above. LineNumber must be unique, but only within Order/Lines.
Is it possible to allow keyref to contain non existing virtual value (our service uses some predefined... let say things. Custom ones are defined in XML to allow extending functionality, but in most of the cases, users will use predefined ones)
Is there any way to determine if list of elements within a tag (something like Lines above) has at least one tag with attribute set to certain value. Good example would be to describe it like a list of tables with unique names, that has list of columns with unique names and at least one of the columns is a primary key.
This is the corrected constraint for Lines/Line:
<xs:complexType name="Order">
<xs:sequence>
<xs:element minOccurs="1" maxOccurs="1" name="Lines" nillable="false" type="t:OrdersLinesList">
<!-- THE PROBLEM SOLVED -->
<xs:key name="LineNoKey">
<xs:selector xpath="t:Line"/>
<xs:field xpath="#LineNumber"/>
</xs:key>
</xs:element>
</xs:sequence>
<xs:attribute name="Number" use="optional" type="xs:string"/>
<xs:attribute name="ClientId" use="optional" type="xs:int"/>
</xs:complexType>
If always helps if you can visualize your constraints, to understand the scope they act upon:
The correct diagram:
vs. the original one:
You can see that the selector rooted in the element Line is looking for yet another Line (./t:Line); and even if you fix the selector, it'll always match at most one attribute. The idea of a key is that the selector should match a set of nodes among which the field must be present and unique.
The above should take care of 1.
No.
Not based on an attribute. To stick with your parallel, for XSD 1.0 I would probably enforce an element called PrimaryKey, which should contain one or more references to names of the other columns; as if instead of using the PRIMARY KEY constraint clause in a column definition, I would enforce the use of the same at the table level.

Complex XPaths using EclipseLink MOXy and JAXB

I am currently using EclipseLink MOXy 2.4.1 and trying to update an element's value via XPaths.
The input used is :
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<expenseReport>
<user>
<userName>Sanaulla</userName>
</user>
<items>
<item>
<itemName>Seagate External HDD</itemName>
<purchasedOn>August 24, 2010</purchasedOn>
<amount>6776.5</amount>
</item>
<item>
<itemName>External HDD</itemName>
<purchasedOn>August 24, 2010</purchasedOn>
<amount>677336.5</amount>
</item>
</items>
</expenseReport>
The XSD is
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="expenseReport" type="ExpenseT"/>
<xs:complexType name="ExpenseT">
<xs:sequence>
<xs:element name="user" type="UserT"/>
<xs:element name="items" type="ItemListT"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="UserT">
<xs:sequence>
<xs:element name="userName" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="ItemListT">
<xs:sequence>
<xs:element name="item" type="ItemT" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="ItemT">
<xs:sequence>
<xs:element name="itemName" type="xs:string"/>
<xs:element name="purchasedOn" type="xs:string"/>
<xs:element name="amount" type="xs:decimal"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
And my Java code is :
JAXBContext context = JAXBContext.newInstance("sample.jaxb.xsd");
JAXBElement<ExpenseT> element = (JAXBElement<ExpenseT>)unmarshaller.unmarshal(new File("resources/sample_before.xml"));
ExpenseT expenseReport = element.getValue();
context.setValueByXPath(expenseReport, "items/item[1]/amount/text()", null, "100.11");
/** Marshalling code **/
I have my java classes created from the XSD using Moxy's tool "jaxb-compiler.cmd".
As you can see from the above code, I am trying to set the amount of 1st item to "100.11". But it doesn't set the value, nor does it throw any exception.
I tried setting the username above using XPath like this
context.setValueByXPath(expenseReport, "user/userName/text()", null, "ABC");
And, it does set/update the value properly.
Can you please advise on how can I set values for complex XPaths with Predicates? Something like this :
items/item[itemName='Seagate External HDD']/amount
We recently fixed a bug in our EclipseLink 2.4.2 and 2.5.0 streams related to setting values in which the XPath contains a postional indicator (ie "foo[1]/bar[2]/text()"). You can download a nightly build from the following link:
http://www.eclipse.org/eclipselink/downloads/nightly.php
You can use predicates in mappings with #XmlPath (see: http://blog.bdoughan.com/2011/03/map-to-element-based-on-attribute-value.html), but we currently don't supports this with our setValueByXPath call. Could you open an enhancement

case-insensitive key in xsd

I have an XSD embedded into an XML like this:
<Replacements>
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Replacements">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="Replace" />
</xs:sequence>
</xs:complexType>
<xs:key name="ReplaceKey">
<xs:selector xpath="./Replace"/>
<xs:field xpath="#old"/>
</xs:key>
</xs:element>
<xs:element name="Replace">
<xs:complexType>
<xs:attribute name="old" type="AnythingButLowerCase" use="required" />
<xs:attribute name="new" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
<xs:simpleType name="AnythingButLowerCase">
<xs:restriction base="xs:string">
<xs:pattern value="[^a-z]+"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
<Replace old="A1020____9" new="A1020"/>
<Replace old="a1020____9" new="A1020"/>
</Replacements>
I've used xs:key to define a unique-key on "old" attribute of Replace elements.
my problem is I want this key to be CASE-INSENSITIVE.
I've read so many documents indicating I can use xsd functions like upper-case or translate to solve this, but if I write something like
<xs:field xpath="upper-case(#old)"/>
VS2010 gives me a warning like this:
'upper-case(#old)' is an invalid XPath for selector or field.
What is it I'm doing wrong?
Thanks :)
The correct XPath function is "upper-case", not "upper case". Just add in the hyphen.
OK!
I got that!
Using functions in an xpath for a xs:field is not allowed.
The workaround for what I was seeking is to define a simpleType and put a restriction there not allowing lower-case letters.
Something like this:
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<Replacements>
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Replacements">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="Replace" />
</xs:sequence>
</xs:complexType>
<xs:key name="ReplaceKey">
<xs:selector xpath="./Replace"/>
<xs:field xpath="#old"/>
</xs:key>
</xs:element>
<xs:element name="Replace">
<xs:complexType>
<xs:attribute name="old" type="AnythingButLowerCase" use="required" />
<xs:attribute name="new" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
<xs:simpleType name="AnythingButLowerCase">
<xs:restriction base="xs:string">
<xs:pattern value="[^a-z]+"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
<Replace old="A1020____9" new="A1020"/>
<Replace old="a1020____9" new="A1020"/>
</Replacements>
Now this serves as what I want it to.

BizTalk generated XSD fails to validate the XML its derived from

I've got an XML response from another system, but no XSD, so I used the Create Schema option to generate one.
I then added the XSD to my BizTalk 2006 R2 project and set its "Input Instance Filename" property to the original XML message.
Tried the "Validate Instance" option and it FAILS ???, with a couple of errors like so ...
error BEC2004: The xsi:type attribute value 'http://www.w3.org/2001/XMLSchema:int' is not valid for the element 'http://www.aniteps.com/xml/schemas/awm/images4:NumberOfErrors', either because it is not a type validly derived from the type in the schema, or because it has xsi:type derivation blocked.
How the heck can the XML fail that was used to generate the XSD ?
The XML example I have is ...
<?xml version="1.0" encoding="utf-8"?>
<ImportIndexDocumentResponse
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.aniteps.com/xml/schemas/awm/images4">
<HasErrors>false</HasErrors>
<NumberOfErrors xsi:type="xsd:int">0</NumberOfErrors>
<ErrorDescription xsi:type="xsd:string">No exception ocurred.</ErrorDescription>
<ErrorNumber xsi:type="xsd:int">0</ErrorNumber>
<FailedItems>
<Item>
<OriginalDataString xsi:type="xsd:string" />
<ErrorDescription xsi:type="xsd:string" />
</Item>
</FailedItems>
<UniqueDocumentReferences>
<UniqueDocumentReference>FA40FE</UniqueDocumentReference>
<UniqueDocumentReference>U55922</UniqueDocumentReference>
</UniqueDocumentReferences>
</ImportIndexDocumentResponse>
And BizTalk / Visual Studio 2005 generates ...
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
attributeFormDefault="unqualified"
elementFormDefault="qualified"
targetNamespace="http://www.aniteps.com/xml/schemas/awm/images4">
<xs:element name="ImportIndexDocumentResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="HasErrors" type="xs:boolean" />
<xs:element name="NumberOfErrors" type="xs:unsignedByte" />
<xs:element name="ErrorDescription" type="xs:string" />
<xs:element name="ErrorNumber" type="xs:unsignedByte" />
<xs:element name="FailedItems">
<xs:complexType>
<xs:sequence>
<xs:element name="Item">
<xs:complexType>
<xs:sequence>
<xs:element name="OriginalDataString" />
<xs:element name="ErrorDescription" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="UniqueDocumentReferences">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" name="UniqueDocumentReference" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xsd:schema>
The XSD generator is reasonably dumb, and didn't notice that the sample instance document contained type annotations (xsi:type attributes). So it decided that <ErrorDescription> should contain unsigned bytes and not signed integers, as the type annotation said.
What happens then is that the validator becomes confused because there are two distinct type definitions for the element, so who should it believe? You could try changing the schema so that the type definitions match the xsi:type overrides, that may help a bit.

Resources