Can I require an XML attribute to have a value? - xsd

This is (part of) the XML that I want to define in my schema. I have already added a unique constraint for the name attribute of the <add /> element.
<parameters>
<add name="one" value="1" />
<add name="two" value="2" />
</parameters>
But I don't know how to prevent <add name="" value="" />. I have tried the following schema, but it's not honored:
<xs:attribute name="name" use="required" type="config:NonEmptyString" />
<xs:simpleType name="NonEmptyString">
<xs:restriction base="xs:string">
<xs:minLength value="1" />
</xs:restriction>
</xs:simpleType>
config is the target namespace for the schema.
Edit: I'm using Visual Studio to validate XML as I write it in the XML editor.

I did a quick test; created an XSD out of the XML and added your constraint:
<?xml version="1.0" encoding="utf-8"?>
<!--XML Schema generated by QTAssistant/XML Schema Refactoring (XSR) Module (http://www.paschidev.com)-->
<xsd:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="parameters">
<xsd:complexType>
<xsd:sequence>
<xsd:element maxOccurs="unbounded" name="add">
<xsd:complexType>
<xsd:attribute name="name" type="NonEmptyString" use="required"/>
<xsd:attribute name="value" type="xsd:unsignedByte" use="required"/>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:simpleType name="NonEmptyString">
<xsd:restriction base="xsd:string">
<xsd:minLength value="1"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
I've validated this XML:
<parameters>
<add name="" value="1" />
<add name="two" value="2" />
</parameters>
And I've got this error:
Error occurred while loading [], line 2 position 8
The 'name' attribute is invalid - The value '' is invalid according to its datatype 'NonEmptyString' - The actual length is less than the MinLength value.
I would say that the problem is rather with your XSD processor, as opposed to the XSD itself. Maybe you could update the post with the processor you're using?

Visual Studio 2010 does the validation correctly - it produces the warning:
Warning 4 The 'name' attribute is invalid - The value '' is invalid according to its datatype 'config:NonEmptyString' - The actual length is less than the MinLength value. XMLFile1.xml 3 14 Miscellaneous Files
but for some reason (bug?) it does not underline the error position in the XML editor.

Related

Unmarshalling xsd with selective element replacement from another xsd

I am new to working with xsd and jaxb, so if my questions are ignorant, please educate me. Also, if you need any more info, let me know and I will provide what I can.
At our company we are working with xsd sources from a 3rd party. We need to implement a SOAP - Java translation and we have a bunch of .wsdl and .xsd files to work with. We are running into problems with two of the .xsd files. The 3rd party provides a "datatypes.xsd", with a org.hl7.v3 namespace and a "datatypes-extensions-hl7nl.xsd", with a nl.hl7.v3 namespace.
When I unmarshall the xds sources, the resultant .java files get created under a different package, named after their own namespaces: org/hl7/v3 and nl/hl7/v3.
Whereas the 3rd party has intended that, where applicable, the types from "datatypes-extensions.xsd" have precedence and should be generated instead of those in "datatypes.xsd", and in the same package.
What I have tried so far
Since I cannot alter the xsd sources, I have (unsuccessfully) tried 2 things using a .jxb file.
1: generating the .java files in a single directory. This led to overwriting issues.
2: providing a binding to point to the correct type:
<jaxb:bindings schemaLocation="../coreschemas/datatypes.xsd">
<jaxb:bindings node="//xs:complexType[#name='TEL']">
<jaxb:class ref="nl.hl7.v3.TEL"/>
</jaxb:bindings>
</jaxb:bindings>
This worked initially, until I changed the reference of a supertype, at which point the compiler complained it could no longer locate the proper supertype for the extending types.
Sources
The sources are opensource so if you'd like to see them for yourself: https://decor.nictiz.nl/pub/vzvz/kz-vzvz-xml-20190122T131422.zip
The .wsdl:
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:hl7="urn:hl7-org:v3"
targetNamespace="urn:hl7-org:v3"
name="OpvragenOverdrachtconcerns">
<documentation> WSDL implementatie van OpvragenOverdrachtconcerns</documentation>
<types>
<xsd:schema targetNamespace="urn:hl7-org:v3" elementFormDefault="qualified">
<xsd:include schemaLocation="../schemas_codeGen/REPC_IN990110NL.xsd"/>
</xsd:schema>
<xsd:schema targetNamespace="urn:hl7-org:v3" elementFormDefault="qualified">
<xsd:include schemaLocation="../schemas_codeGen/REPC_IN990111NL.xsd"/>
</xsd:schema>
</types>
<message name="REPC_IN990110NL">
<part name="body" element="hl7:REPC_IN990110NL"/>
</message>
<message name="REPC_IN990111NL">
<part name="body" element="hl7:REPC_IN990111NL"/>
</message>
The header of response message type: REPC_IN990111NL:
<?xml version="1.0" encoding="UTF-8"?>
<!-- REPC_IN990111NL - Opleveren overdrachtconcerns --><!--Note: this file was generated. DO NOT EDIT HERE.--><xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="urn:hl7-org:v3"
targetNamespace="urn:hl7-org:v3"
elementFormDefault="qualified">
The header and definition of a conflicting type in datatypes.xsd:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:hl7="urn:hl7-org:v3" xmlns:hl7nl="urn:hl7-nl:v3"
xmlns:sch="http://www.ascc.net/xml/schematron" elementFormDefault="qualified" targetNamespace="urn:hl7-org:v3" xmlns="urn:hl7-org:v3">
<xsd:include schemaLocation="voc.xsd"/>
<xsd:import namespace="urn:hl7-nl:v3" schemaLocation="datatypes-extensions-hl7nl.xsd"/>
<xsd:complexType name="TEL">
<xsd:complexContent>
<xsd:extension base="URL">
<xsd:sequence>
<xsd:element name="useablePeriod" type="IVL_TS" minOccurs="0"
maxOccurs="unbounded">
<!-- FIXME: one would expect the name "GTS" here but it's not
SXCM does ALL the right things, it's just not the right NAME. -->
</xsd:element>
<xsd:element name="id" type="II" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="use" type="set_cs_TelecommunicationAddressUse" use="optional">
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
The header and type in datatypes-extension-hl7nl.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" xmlns:hl7="urn:hl7-org:v3" xmlns="urn:hl7-nl:v3" xmlns:sch="http://purl.oclc.org/dsdl/schematron" targetNamespace="urn:hl7-nl:v3">
<xsd:import schemaLocation="datatypes.xsd" namespace="urn:hl7-org:v3"/>
<xsd:complexType name="TEL">
<xsd:complexContent>
<xsd:extension base="ANY">
<xsd:sequence>
<xsd:element name="useablePeriod" type="QSET_TS" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="value" type="xsd:anyURI" use="optional"/>
<xsd:attribute name="use" type="set_TelecommunicationAddressUse" use="optional"/>
<xsd:attribute name="capabilities" type="set_TelecommunicationCapability" use="optional"/>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
Expected and actual results
As stated above, instead of generating two packages according to the different namespaces, one should be created with the "nl.hl7.v3" types being generated intead of the "org.hl7.v3" ones with the same name.
Thank you for your time in advance.
Max

Spring-ws validation of schema with multiple imports to same namespace

I have a number of required soap headers defined in XSDs that I am not allowed to change, as existing clients are already using these in production.
In one of these schemas there are a number of imports with the same namespace value. When I attempt loading this schema into my validation interceptor I get an exception saying that the sdsd:SystemName (2nd element in the sequence) is undefined.
If I open the XSD in IntelliJ Idea 13 I get red markings for sdsd:SystemName and the rest of the list of elements. Only the sdsd:SystemOwnerName is found and loaded.
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:sdsd="http://www.sdsd.dk/dgws/2010/08" xmlns:sdsd201206="http://www.sdsd.dk/dgws/2012/06" targetNamespace="http://www.sdsd.dk/dgws/2012/06" elementFormDefault="qualified" attributeFormDefault="unqualified">
<import namespace="http://www.sdsd.dk/dgws/2010/08" schemaLocation="../../2010/08/SystemOwnerName.xsd" />
<import namespace="http://www.sdsd.dk/dgws/2010/08" schemaLocation="../../2010/08/SystemName.xsd" />
<import namespace="http://www.sdsd.dk/dgws/2010/08" schemaLocation="../../2010/08/SystemVersion.xsd" />
<import namespace="http://www.sdsd.dk/dgws/2010/08" schemaLocation="../../2010/08/OrgResponsibleName.xsd" />
<import namespace="http://www.sdsd.dk/dgws/2010/08" schemaLocation="../../2010/08/OrgUsingName.xsd" />
<import namespace="http://www.sdsd.dk/dgws/2010/08" schemaLocation="../../2010/08/OrgUsingID.xsd" />
<import namespace="http://www.sdsd.dk/dgws/2010/08" schemaLocation="../../2010/08/RequestedRole.xsd" />
<element name="WhitelistingHeader" type="sdsd201206:WhitelistingHeader">
<annotation>
<documentation xml:lang="en-GB">SDSD Whitelisting header.</documentation>
<documentation xml:lang="da-DK">SDSD Whitelisting header.</documentation>
</annotation>
</element>
<complexType name="WhitelistingHeader">
<sequence>
<element ref="sdsd:SystemOwnerName" minOccurs="1" maxOccurs="1" />
<element ref="sdsd:SystemName" minOccurs="1" maxOccurs="1" />
<element ref="sdsd:SystemVersion" minOccurs="1" maxOccurs="1" />
<element ref="sdsd:OrgResponsibleName" minOccurs="1" maxOccurs="1" />
<element ref="sdsd:OrgUsingName" minOccurs="1" maxOccurs="1" />
<element ref="sdsd:OrgUsingID" minOccurs="1" maxOccurs="1" />
<element ref="sdsd:RequestedRole" minOccurs="1" maxOccurs="1" />
</sequence>
</complexType>
`
I have read this thread One xml namespace equals one and only one schema file? and can confirm that if I make a new 'master' schema that includes the schemas that are imported in the schema shown above and then change the imports in the schema shown above to a single include of the 'master' schema my Spring-ws validation interceptor is working correctly.
However since changing the schema is not an option I am looking for other options.
I have found Xerces documentation and Validate XML with loading schemas at runtime, failure depending on schema order suggesting that I can set the feature "http://apache.org/xml/features/validation/schema/handle-multiple-imports" to true on the XmlSchemaFactory in order to make Xerces not fail when validating a schema with multiple imports to the same namespace. However I have my own SoapHeaderValidatingInterceptor that extends the AbstractValidatingInterceptor, which in turn uses the Spring WS internal XmlValidatorFactory to create the XmlValidator that is used to validate the XSDs.
Any tips as to how I can enable the handle-multiple-imports feature will be greatly appreciated.

Xml Schema with AnyAttribute, add attribute to specific element

If I have two elements with the <anyattribute/> element in my schema like this:
<xs:element name="NodeType1">
<xs:complexType>
<xs:anyAttribute />
</xs:complexType>
</xs:element>
<xs:element name="NodeType2">
<xs:complexType>
<xs:anyAttribute />
</xs:complexType>
</xs:element>
Is it possible to extend only one of those elements in another schema? Let's say I wanted to add an attribute to NodeType2 only.
Elements are not extensible; in general, you will have to create a named (global, under the schema element) type if you wish to use as a base for extension anywhere else, be that in the same or another XML Schema.
Your question is very interesting because it really makes one wonder what is the purpose of extending something that by definition could match anything, anyhow. For that, the effect of the extension is really the opposite; it creates a constraint for the attribute(s) named in the extension.
So, the first XSD:
<?xml version="1.0" encoding="utf-8" ?>
<!--W3C Schema generated by QTAssistant/W3C Schema Refactoring Module (http://www.paschidev.com)-->
<xsd:schema targetNamespace="http://tempuri.org/XMLSchema.xsd"
elementFormDefault="qualified"
xmlns="http://tempuri.org/XMLSchema.xsd"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="root" type="BaseType"/>
<xsd:complexType name="BaseType">
<xsd:anyAttribute processContents="lax" />
</xsd:complexType>
<xsd:complexType name="Extending">
<xsd:complexContent>
<xsd:extension base="BaseType">
<xsd:attribute name="new1" type="xsd:int"/>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:schema>
With this schema, the following sample XML is perfectly valid:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!-- Sample XML generated by QTAssistant (http://www.paschidev.com) -->
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" new1="S" new2="2" xmlns="http://tempuri.org/XMLSchema.xsd"/>
Now, if I'm changing
<xsd:element name="root" type="BaseType"/>
to
<xsd:element name="root" type="Extending"/>
the same sample XML if no longer valid:
Error occurred while loading [], line 3 position 61
The 'new1' attribute is invalid - The value 'S' is invalid according to its datatype 'http://www.w3.org/2001/XMLSchema:int' - The string 'S' is not a valid Int32 value.
Changing the S to a numeric, it will make the XML valid.
Isn't that a funny thing about "extending"?...

XSD element with undefined contents

I need to rig up an XSD schema that will validate files partially. The file structure is:
<Root>
<Node name="core">
<ElementA>String</ElementA>
<ElementB>String</ElementB>
</Node>
<Node name="something unique">
(any number of elements, with unknown names and types)
</Node>
</Root>
My XSD is something like:
<xs:element name="Root">
<xs:complexType>
<xs:sequence maxOccurs="unbounded">
<xs:element name="Node">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" />
</xs:sequence>
<xs:attribute name="name" type="xs:string" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
Which is incomplete and not entirely correct, the un-named <xs:element> is invalid.
There are a few nodes that are required, as well as each node having a unique name attribute; this is what I want to validate. The list of names, and the contents of those nodes, is predefined.
The contents of nodes with unknown names is also unknown, and may contain any number of elements with any name and type, but must not have attributes or values themselves.
The part I'm having trouble with is allowing child elements without knowing their names.
Is it at all possible to do something like this with XSD? Is there a way to have a complex type of elements, or anyType, and an attribute?
Edit: It would be just as acceptable to use the <Node> names as the element type, and then simply allow additional elements with unknown names. Either way, I need to allow nodes with unknown name and type.
To allow "child elements without knowing their names" you could use xsd:any; add it as a repeating particle after your specific (known at "design time") content.
<?xml version="1.0" encoding="utf-8"?>
<!--W3C Schema generated by QTAssistant/W3C Schema Refactoring Module (http://www.paschidev.com)-->
<xsd:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="Root">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Node">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="ElementA" type="xsd:string" />
<xsd:element name="ElementB" type="xsd:string" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
<xsd:element name="Extensions" minOccurs="0">
<xsd:complexType>
<xsd:sequence>
<xsd:any maxOccurs="unbounded" processContents="lax"/>
</xsd:sequence>
<xsd:anyAttribute processContents="lax"/>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>

XJC Generating Integer Instead of int

The following schema should be generating two primitive int fields in a Value class, but instead generates a primitive int for the element and java.lang.Integer for the attribute.
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema version="1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.com/test" xmlns:test="http://www.example.com/test"
elementFormDefault="qualified">
<xsd:element name="values">
<xsd:complexType>
<xsd:sequence minOccurs="0" maxOccurs="unbounded">
<xsd:element ref="test:value" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="value">
<xsd:complexType>
<xsd:sequence>
<!-- Is generated as primitive int -->
<xsd:element name="element" type="xsd:int" />
</xsd:sequence>
<!-- Is generated as java.lang.Integer -->
<xsd:attribute name="attribute" type="xsd:int" />
</xsd:complexType>
</xsd:element>
</xsd:schema>
I've looked through the JAXB documentation for anything that says that attributes and elements may be generated differently and found nothing.
Can anyone explain this? Is there a fix to make the attribute generate as a primitive int?
I'm not entirely sure this is the answer, but I had an epiphany while debugging my app.
The default multiplicity for an element in an XML schema is 1..1 (required) where as the default multiplicity for an attribute is 0..1 (optional).
So, since the element is required and a primitive in Java has a default value (most likely 0), it makes sense to generate an <xsd:element type="xsd:int" /> as a Java primitive.
Since the attribute is optional there is a possibility that it may be nillable which would not be possible using a primitive. The java.lang.Integer is an Object and thus allowed to be null, so it makes sense to generate an <xsd:attribute type="xsd:int" /> as an java.lang.Integer.
If you make an attribute be required (<xsd:attribute type="xsd:int" use="required" />), it will generate as a primitive int. I haven't seen documentation by JAXB that explicitly says this, but that doesn't mean it doesn't exist; perhaps I just missed it.

Resources