XML Schema: require an element to be present when another is present - xsd

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.

Related

XML Schema same attributes names but different specific attribute sets of values?

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>

cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found

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.

Schema with elements, attributes, and text

I am having trouble getting this XML file to validate against my schema, which doesn't have syntax errors according to my XML editor. I am trying to make course an complexType element, but it keeps telling me I can't. The XML is correct, it is definitely something with my schema, I just can't figure it out.
Here is the XML:
<?xml version="1.0" encoding="utf-8"?>
<courses xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="course_offerings.xsd">
<course id="WEB225">
<name>Web Development II</name>
<offered>Spring</offered>
<pre_reqs>WEB125</pre_reqs>
</course>
<course id="WEB125">
<name>Web Development I</name>
<offered>Fall</offered>
</course>
<course id="WEB325">
<name>Client-Side Scripting</name>
<offered>Spring</offered>
<offered>Fall</offered>
<pre_reqs>WEB225</pre_reqs>
</course>
</courses>
And here is my schema:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="courses">
<xs:complexType>
<xs:sequence>
<xs:element name="course" type="xs:string"/>
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="offered" type="xs:string"/>
<xs:element name="pre_reqs" type="xs:string"/>
</xs:sequence>
</xs:sequence>
<xs:attribute name="id" type="xs:string"/>
</xs:complexType>
</xs:element>
</xs:schema>
Since you haven't mentioned what error you are getting, I'm providing what I can observe..
In your XML you have included this statement: xsi:noNamespaceSchemaLocation="course_offerings.xsd" This means it is your default XML schema. You need to verify the name of schema and make sure it is present in default path.. (same as that of XML file). Otherwise you may end up seeing an error unable to locate schema
course_offerings.xsd
You have declared <xs:element name="course" type="xs:string"/> as string .. that should not be the case.. In your XML it's a complexType, ie, an element having child elements inturn..
All these elements name, offered, pre_reqs should come under this complexType
Attribute should be within the scope of this complexType..
Otherwise you would face not just one but multiple errors since the definition of element course is invalid
Refer the sample XSD below:
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="courses">
<xs:complexType>
<xs:sequence>
<xs:element name="course">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="offered" type="xs:string"/>
<xs:element name="pre_reqs" type="xs:string"/>
</xs:sequence>
<xs:attribute name="id" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
The above mentioned style is hierarchical, there is an alternative method to write a schema file.. If you understand the current consequences and if you wish to know further then I will let you know..
For now this much explanation should be good..

Why won't XML Schema allow me to define a one-to-many key? And how do I do so?

I'm falling over on a frustrating, arbitrary restriction in XML Schema. For some reason, it insists that PK-FK relationships have to be one-to-one. Why?
For example, given the schema:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="FutureSchema"
targetNamespace="http://tempuri.org/FutureSchema.xsd"
elementFormDefault="unqualified"
xmlns="http://tempuri.org/FutureSchena.xsd"
xmlns:mstns="http://tempuri.org/FutureSchema.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="FUTUREFILE">
<xs:complexType>
<xs:sequence>
<xs:element name="Configuration">
<xs:complexType>
<xs:sequence>
<xs:element name="Experiments">
<xs:complexType>
<xs:sequence>
<xs:element name="Experiment">
<xs:complexType>
<xs:attribute name="ID" type="xs:integer"/>
<xs:attribute name="Profile" type="xs:integer"/>
</xs:complexType>
<xs:keyref name="dummy" refer="LP">
<xs:selector xpath="Experiment"/>
<xs:field xpath="#Profile"/>
</xs:keyref>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:key name="LP">
<xs:selector xpath="*/Configuration/Profiles/Profile"/>
<xs:field xpath="#ID"/>
</xs:key>
</xs:element>
<xs:element name="Profiles">
<xs:complexType>
<xs:sequence>
<xs:element name="Profile">
<xs:complexType>
<xs:attribute name="ID" type="xs:integer"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
And an example instance:
<?xml version="1.0" encoding="utf-8" ?>
<b:FUTUREFILE xmlns:b="http://tempuri.org/FutureSchena.xsd">
<Configuration>
<Experiments>
<Experiment ID="1" Profile="1"/>
<Experiment ID="2" Profile="1"/>
</Experiments>
<Profiles>
<Profile ID="1"/>
</Profiles>
</Configuration>
</b:FUTUREFILE>
Document validation throws an error if I define <Experiment ID="1" FK="1"/><Experiment ID="2" FK="1"/>, for example; i.e. more than one Experiment may not reference the same Profile. But why else would I want to use a key relationship? What use is a key relationship at all if I can't do something so fundamental?
OK, if and won't let me do this, how should I?
edit #1: As requested, I've padded out my code sample to include the full schema and a basic instance.
edit #2: Interesting. SharpDevelop's XML editor (as opposed to Visual Studio's) doesn't seem to object. It doesn't object to the foreign key value referring to a nonexistent primary key either (which IMO it should) but it's a start.
What wasn't clear ?... My english, it's all :-)
Some remarqs, I'm not sure it's solution :
In exemple instance, it's best to use xmlns:b="http://tempuri.org/FutureSchema.xsd">, and not xmlns:b="http://tempuri.org/FutureSchena.xsd"> (n -> m).
Also it's best to put b: in front of all elements names.
According to your schema, you can't have two Experiment in Experiments, only one.
On xsd, put <xs:keyref name="dummy" refer="mstns:LP">, that works best for me ; it's because xpath expression doesnt't understand default namespace, see Correct way to use key in xsd.

How to define the content of an element to be unique?

How can i define that the content of the emailaddress-element has to be unquie compared to all other emailaddresses entered inside the users-tag?
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="users">
<xs:sequence>
<xs:element name="user">
<xs:element name="name" type="xs:string" />
<xs:element name="emailaddress" type="xs:string" />
</xs:element>
</xs:sequence>
</xs:element>
I think this is what you are after:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="users">
<xs:complexType>
<xs:sequence maxOccurs="unbounded">
<xs:element name="user">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="emailaddress" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
<!-- Make sure each user has a unique email address -->
<xs:unique name="email-address-is-unique">
<xs:selector xpath="user"/>
<xs:field xpath="emailaddress"/>
</xs:unique>
</xs:element>
</xs:schema>
I also took the liberty of adding omitted elements from your original schema for completeness.
So the xpath attribute of the selector element defines the elements that are being used by the uniqueness constraint, then the field element(s) have xpaths which determine what needs to be unique across the selected elements.
You use the <xs:unique> tag as described here

Resources