I have the following xsd
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element ref="age"/>
<xs:group ref="gp.contacts"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:group name="gp.contacts">
<xs:sequence>
<xs:element ref="name" maxOccurs="unbounded"/>
<xs:element ref="phone" maxOccurs="unbounded"/>
<xs:element ref="address" maxOccurs="unbounded"/>
</xs:sequence>
</xs:group>
</xs:schema>
</xs:schema>
Then I'm using jaxb when I create xml, the output is
<root>
<age>25to35</age>
<contacts>
<name>...</name>
<name>...</name>
<name>...</name>
<phone>...</phone>
<phone>...</phone>
<phone>...</phone>
<address>..</address>
<address>..</address>
<address>..</address>
</contacts>
</root>
But I want the output to be like this
<root>
<age>25to35</age>
<contacts>
<name>...</name>
<phone>...</phone>
<address>..</address>
<name>...</name>
<phone>...</phone>
<address>..</address>
<name>...</name>
<phone>...</phone>
<address>..</address>
</contacts>
</root>
Can someone please tell me if this output can be achieved through modifying the xsd or jaxb or by any other way.
If you want to allow unbounded sequences, each containing one (name, phone, address), in that order, you need to remove it from the containing elements (which will now allow and require only one of each, which is the default):
<xs:group name="gp.contacts">
<xs:sequence>
<xs:element name="name"/>
<xs:element name="phone"/>
<xs:element name="address"/>
</xs:sequence>
</xs:group>
Then you need to declare that the sequence is unbounded. Since you declared a group, you do that when you reference it:
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element ref="age"/>
<xs:group ref="gp.contacts" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
This might not solve your problem yet. You said that JAXB was generating the XML you included in your question with the <contacts> element. Your schema does not validate that. I assume you are wrapping that in JAXB (you didn't show your code), but if you can edit the schema it's better to do so since your XML will validate against it). The schema as is actually validates this:
<root>
<age>25to35</age>
<name>...</name>
<name>...</name>
...
<address>..</address> ...
<phone>...</phone>
...
</root>
With the modifications, now it validates this:
<root>
<age>25to35</age>
<name>...</name>
<phone>...</phone>
<address>..</address>
<name>...</name>
<phone>...</phone>
<address>..</address>
<name>...</name>
<phone>...</phone>
<address>..</address>
...
</root>
For it to validate the XML you want it to generate, with the <name>, <phone> and <address> sequences nested in <contacts>, you need to add a declaration for the <contacts> element in XML Schema, and reference the group from inside it:
<xs:element name="root">
<xs:complexType>
<xs:sequence maxOccurs="unbounded">
<xs:element name="age" type="xs:string"/>
<xs:element name="contacts">
<xs:complexType>
<xs:group ref="gp.contacts" maxOccurs="unbounded"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
Your schema also has doubled <schema> root elements (I assumed that was a cut-and-paste typo.)
If you fix these problems, you can use the schema to generate classes for JAXB that will create XML the instances you want.
Related
I have an XSD to validate an XML file. The structure is as follows:
<root>
<child>
<size>2</size>
<childElement>Element 1</childElement>
<childElement>Element 2</childElement>
</child>
</root>
The number of childElements is dependent on the size provided i.e. if size was set as 3, not more than 3 childElements can be added.
I have tried using xs:alternative but it does not seem to work:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element name="child" minOccurs="1" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="size" type="xs:integer" maxOccurs="1"/>
<xs:element name="childElement" type="xs:string" maxOccurs="1">
<xs:alternative test="#size>1" maxOccurs="#size"/>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Is there a way of using xs:alternative or another tag to achieve this, or is this outside the realm of possibility with XSD?
Design recommendation: If your XML design can still be changed, eliminate the size element and convey that information implicitly rather than explicitly. By eliminating the duplication of information, you'll not need to check that the duplication is consistent.
If your XML design cannot still be changed, or if you choose not to change it...
XSD 1.0
Not possible. Would have to be checked out-of-band wrt XSD.
XSD 1.1
Possible using xs:assert:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema attributeFormDefault="unqualified"
elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
vc:minVersion="1.1">
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element name="child">
<xs:complexType>
<xs:sequence>
<xs:element name="size" type="xs:integer"/>
<xs:element name="childElement" maxOccurs="unbounded"/>
</xs:sequence>
<xs:assert test="count(childElement) = size"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
I have a short question to my XSD Problem.
I have created an test.xsd file how should handle 2 XML types.
One for my database and one for an third party application.
It works great whether I use the database XML files, but in the third Party software the XML tag is on another position. Let me explain:
Database XML summary:
<tempData> 123456 </tempData>
<DataSet> 505 </DataSet>
third party software xml summary:
<DataSet> 505 </DataSet>
<tempData> 123456 </tempData>
XSD summary:
<xs:complexType>
<xs:sequence>
<xs:element name="Data" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element ref="tempData" minOccurs="0" maxOccurs="unbounded"/>
<xs:element ref="DataSet" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="tempData" />
<xs:element ref="DataSet" />
</xs:choice>
</xs:complexType>
</xs:element>
When I would like to validate these two different XML files with my XSD file for the database XML file it works and for the third party XML file with the inverted tags it will not validate.
How can I handle these two different arrangements?
below is a solution that will allow both 'DataSet' and 'tempData' to be present in the 'Data' element, either both at the same time (in any order), one or the other alone, or neither of them (empty 'Data' element).
If you wish to force either one to be present, change the minOccurs to '1'.
You cannot have more than one of each of these elements within the 'Data' element when using 'xs:all' - either minimum 0 or 1.
<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Data">
<xs:complexType>
<xs:all>
<xs:element name="tempData" minOccurs="0" />
<xs:element name="DataSet" minOccurs="0" />
</xs:all>
</xs:complexType>
</xs:element>
</xs:schema>
Try it with:
<Data>
<DataSet> 505 </DataSet>
<tempData> 123456 </tempData>
</Data>
<Data>
<tempData> 123456 </tempData>
<DataSet> 505 </DataSet>
</Data>
<Data>
<DataSet> 505 </DataSet>
</Data>
<Data>
<tempData> 123456 </tempData>
</Data>
<Data>
</Data>
And your XML will be valid
As Martin has mentioned, this is an XML Schema question, not XSLT.
You need the xs:all element, so soemthing like:
<xs:all>
<xs:element ref="tempData" minOccurs="0" maxOccurs="unbounded"/>
<xs:element ref="DataSet" minOccurs="0" maxOccurs="unbounded" />
</xs:all>
Do you really want both elements to be optional?
I wish to create a repeating same named element with two attributes for which the values of each are tied to each other. i.e.
<anElement id="R1" description="Some definition for R1"/>
<anElement id="R2" description="Some definition for R2"/>
Ideally I would define "groups" of id and description attributes together and reference one of the groups for each instance of anElement element.
<complexType name="RElements">
<choice>
<element name="anElement" type="R1Group"/>
<element name="anElement" type="R2Group"/>
</choice>
</complexType>
<complexType name="RElementsType">
<sequence>
<element ref="RElements" minOccurs="1" maxOccurs="unbounded"/>
</sequence>
</complexType>
But Choice doesn't allow multiples of the same element name. I see discussions about how to have multiple elements of the same name but none allow additional attributes let alone having attributes tied to each other. The only way that I can get close is by having a different named element based on the id. i.e.
<R1 id="R1" description="Some definition for R1"/>
<R2 id="R2" description="Some definition for R2"/>
Any suggestions?
You need to provide more information.
Basically to achieve the XML you have provided a simple schema like this would suffice.
<?xml version="1.0" encoding="utf-8" ?>
<!--Created with Liquid XML 2015 Developer Bundle Edition 13.0.3.5737 (http://www.liquid-technologies.com)-->
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="RootElement">
<xs:complexType>
<xs:sequence>
<xs:element name="anElement" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="id" type="xs:string" />
<xs:attribute name="descritpion" type="xs:string" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
However you mention that the attribute values id and description are linked, you may be able to constrain these, but you need to provide more info. Also I'm not sure why you are looking at choices? Its difficult to see what your attempting give you only provide snippets of the schema
To include the constraints described in later comments the following schema would allow this, but force a change in the XML structure
<AnElement id="E1"> Exterminator serial <ref id="E1"/> </AnElement>
<?xml version="1.0" encoding="utf-8" ?>
<!--Created with Liquid XML 2015 Developer Bundle Edition 13.0.0.5686 (http://www.liquid-technologies.com)-->
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="RootElement">
<xs:complexType>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="AnElement">
<xs:complexType mixed="true">
<xs:sequence>
<xs:element name="ref" minOccurs="0">
<xs:complexType>
<xs:attribute name="id" type="xs:string" use="optional" />
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="id" type="xs:string" use="optional" />
</xs:complexType>
<xs:key name="IDVal">
<xs:selector xpath="." />
<xs:field xpath="#id" />
</xs:key>
<xs:keyref name="IdRef" refer="IDVal">
<xs:selector xpath="ref" />
<xs:field xpath="#id" />
</xs:keyref>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
I am trying to understand <any> element in xsd. I had two xsds.
Book Catalogue.xsd
<?xml version="1.0" encoding="ISO-8859-1"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.w3schools.com" xmlns="http://www.w3schools.com"
elementFormDefault="qualified">
<xs:element name="BookCatalogue">
<xs:complexType>
<xs:sequence>
<xs:element name="Book" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="Title" type="xs:string" />
<xs:element name="Author" type="xs:string" />
<xs:element name="Date" type="xs:string" />
<xs:element name="ISBN" type="xs:string" />
<xs:element name="Publisher" type="xs:string" />
<xs:any namespace="##any" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Reviewer.xsd
<?xml version="1.0" encoding="ISO-8859-1"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.w3schools.com" xmlns="http://www.w3schools.com"
elementFormDefault="qualified">
<xs:element name="Reviewer">
<xs:complexType>
<xs:sequence>
<xs:element name="Name">
<xs:complexType>
<xs:sequence>
<xs:element name="First" type="xs:string" />
<xs:element name="Last" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
But if i validate the below xml based on above xsd, i am getting cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element 'p:Reviewer'. error. Does both xsd file should not be in same namespace?
<?xml version="1.0" encoding="UTF-8"?>
<pr:BookCatalogue xmlns:pr="http://www.w3schools.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.w3schools.com AddRequest.xsd ">
<pr:Book>
<pr:Title>pr:Title</pr:Title>
<pr:Author>pr:Author</pr:Author>
<pr:Date>pr:Date</pr:Date>
<pr:ISBN>pr:ISBN</pr:ISBN>
<pr:Publisher>pr:Publisher</pr:Publisher>
<p:Reviewer xmlns:p="http://www.w3schools.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.w3schools.com Children.xsd ">
<p:Name>
<p:First>p:First</p:First>
<p:Last>p:Last</p:Last>
</p:Name>
</p:Reviewer>
</pr:Book>
</pr:BookCatalogue>
Two options...
Option One: If you do not want to have to have the definition of p:Reviewer present, add processContents="lax" to your xs:any element:
<xs:any namespace="##any" minOccurs="0" processContents="lax"/>
Per XML Schema Part 0: Primer Second Edition:
The lax value of the processContents attribute instructs an XML
processor to validate the element content on a can-do basis: It will
validate elements and attributes for which it can obtain schema
information, but it will not signal errors for those it cannot obtain
any schema information.
See also XML Validation in Java: processContents=“lax” seems not to work correctly.
You should also carefully adjust your xsi:schemaLocation values to point to the actual filename of each XSD for each namespace in play. Here is your XML instance with the changes that I made:
<?xml version="1.0" encoding="UTF-8"?>
<pr:BookCatalogue
xmlns:pr="http://www.w3schools.com"
xmlns:p="http://www.w3schools.com/1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.w3schools.com BookCatalogue.xsd http://www.w3schools.com/1 Reviewer.xsd">
<pr:Book>
<pr:Title>pr:Title</pr:Title>
<pr:Author>pr:Author</pr:Author>
<pr:Date>pr:Date</pr:Date>
<pr:ISBN>pr:ISBN</pr:ISBN>
<pr:Publisher>pr:Publisher</pr:Publisher>
<p:Reviewer>
<p:Name>
<p:First>p:First</p:First>
<p:Last>p:Last</p:Last>
</p:Name>
</p:Reviewer>
</pr:Book>
</pr:BookCatalogue>
Note: Make sure that the targetNamespace in Review.xsd matches what's declared for it in BookCatalogue.xml's xsi:schemaLocation attribute.
Option Two: If you do want to insist that the definition of p:Reviewer be present, just make the above changes to be sure that Review.xsd can be found per the xsi:schemaLocation mechanism. No processContents setting is required; it defaults to strict.
My Schema allows a specific element to be optional, but when I encounter a different also optional element later on in the file, I need the previous one to be present. How can I ensure this via XSD?
Example:
<settings>
<file name="narf.txt"/>
<metafile name="narf.meta"/>
<filtermeta>true</filtermeta>
</settings>
should be valid,
<settings>
<file name="narf.txt"/>
<metafile name="narf.meta"/>
</settings>
and
<settings>
<file name="narf.txt"/>
</settings>
should be valid too,
<settings>
<file name="narf.txt"/>
<filtermeta>true</filtermeta>
</settings>
should not be valid.
Try the following schema definition:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="settings">
<xs:complexType>
<xs:sequence>
<xs:element name="file">
<xs:complexType>
<xs:attribute name="name" type="xs:string"/>
</xs:complexType>
</xs:element>
<xs:sequence minOccurs="0">
<xs:element name="metafile">
<xs:complexType>
<xs:attribute name="name" type="xs:string"/>
</xs:complexType>
</xs:element>
<xs:element minOccurs="0" name="filtermeta" type="xs:string"/>
</xs:sequence>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
I've run your first three examples against this schema using xmllint and they validate correctly. The fourth example fails with:
cvc-complex-type.2.4.a: Invalid content was found starting with element 'filtermeta'. One of '{metafile}' is expected.
as expected.
You could have filtermeta as an optional attribute to the metafile element.