In my schema I have:
<xs:element name="html-script">
<xs:annotation>
<xs:documentation>Element used to specify pass-through Javascript</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:anyAttribute/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
In a document I have:
<html-attributes target="_new"/>
When I validate, I get ...
Validation error: cvc-complex-type.3.2.2: Attribute 'target' is not allowed to appear in element 'html-attributes'. at file:/Users/benson/x/btweb/web_2_0/./content/about-us/about-us.xml line 35 character 38
What am I missing?
Possible Typo? Your schema defines the element <html-script> whereas your document uses <html-attributes>.
Also try adding the processContents directive to your anyAttribute:
<xs:anyAttribute processContents="skip" />
or
<xs:anyAttribute processContents="lax" />
Related
My new XML private language includes elements <figure>, representing illustrations (image + caption).
Whenever illustrations refer to some image in the local database I just want to type
<figure id="9809" width="full" />
to identify image number 9809 and its associated caption.
On the other side, if images come from outside I will need a slightly different syntax:
<figure href="https://some-url-here" width="full">Some ad hoc catpion</figure>
So far I have declared an element that combine both behaviours, like this:
<!-- Figures -->
<xs:simpleType name="FigureWidthEnum">
<xs:restriction base="xs:token">
<xs:enumeration value="center" />
<xs:enumeration value="half" />
<xs:enumeration value="full" />
</xs:restriction>
</xs:simpleType>
<xs:element name="figure">
<xs:complexType mixed="true">
<xs:complexContent>
<xs:extension base="Inline">
<xs:attribute name="href" type="URI" />
<xs:attribute name="id" type="xs:nonNegativeInteger" />
<xs:attribute name="width" type="FigureWidthEnum" default="full" />
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
It works fine but a fresh editor can mess with the 3 attributes and type impossible things I don't want to pass the Schema Validator that easy. For example:
<figure id="9809" width="full" href="https://some-unexpected-url">Some unexpected caption that should not be here</figure>
I want to have two completely separate sintaxes for <figure>, as if I could declare these two elements with the same name:
<xs:element name="figure">
<xs:complexType mixed="true">
<xs:complexContent>
<xs:extension base="Inline">
<xs:attribute name="href" type="URI" />
<xs:attribute name="width" type="FigureWidthEnum" default="full" />
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
<xs:element name="figure">
<xs:complexType>
<xs:attribute name="id" type="xs:nonNegativeInteger" />
<xs:attribute name="width" type="FigureWidthEnum" default="full" />
</xs:complexType>
</xs:element>
In fact it is not possible.
Can it be done somehow?
Yes, it is possible with XSD 1.1, which provides <xs:alternative> element intended specifically for such requirements. Here's a complete XML schema I've designed to validate exactly as you need:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
vc:minVersion="1.1">
<!-- Figures -->
<xs:simpleType name="FigureWidthEnum">
<xs:restriction base="xs:token">
<xs:enumeration value="center" />
<xs:enumeration value="half" />
<xs:enumeration value="full" />
</xs:restriction>
</xs:simpleType>
<!-- stub definition -->
<xs:complexType name="Inline"/>
<!-- 'figure' element is declared once, but its type has two alternatives -->
<xs:element name="figure">
<!-- The first alternative is selected, when the condition specified
in 'test' attribute is true. The condition must be a boolean XPath
expression. The '#id' returns the value of 'id' attribute. However,
when converted to boolean, it indicates whether 'id' attribute is
specified at all. The anonymous complexType inside <xs:alternative>
provides the element type valid for this case.
-->
<xs:alternative test="#id">
<xs:complexType>
<xs:attribute name="id" type="xs:nonNegativeInteger" />
<xs:attribute name="width" type="FigureWidthEnum" default="full" />
</xs:complexType>
</xs:alternative>
<!-- The second alternative has no 'test' attribute. That means, it must
be selected by default, when all other alternatives (with a specified
test condition) do not pass. Here, the anonymous complexType inside
<xs:alternative> defines the element type in case of reference:
when 'href' is present.
-->
<xs:alternative>
<xs:complexType mixed="true">
<xs:complexContent>
<xs:extension base="Inline">
<xs:attribute name="href" type="xs:anyURI" />
<xs:attribute name="width" type="FigureWidthEnum" default="full" />
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:alternative>
</xs:element>
<!-- this element is defined just to test the whole schema in XML below -->
<xs:element name="figures">
<xs:complexType>
<xs:sequence>
<xs:element ref="figure" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
A complete XML file this schema validates:
<?xml version="1.0" encoding="UTF-8"?>
<figures>
<!-- passes validation -->
<figure id="9809" width="full" />
<!-- passes validation -->
<figure width="full" href="https://some-unexpected-url">Some ad hoc caption</figure>
<!-- does not pass the validation -->
<figure id="9809" width="full" href="https://some-unexpected-url">
Some unexpected caption that should not be here
</figure>
</figures>
The validation was done with Apache Xerces 2.11.0 (XSD 1.1 aware).
Promo add-on. These links may be interesting for those working with XML schemas and WSDL: FlexDoc/XML XSDDoc & WSDLDoc – High-performance universal XML Schema / WSDL Documentation Generators with Diagrams
I want to write an XML schema (xsd 1.1) for a document containing options. Each option has a name and a type (like boolean, integer, string, etc ...) and a datum matching that type. The list of types is fixed, but quiet long. (Only 3 are listed in listing 3 for simplicity.)
How do I do this without a ridiculous amount of repetition?
Use case 1
Here is a valid document for this schema..
Listing 1:
<abc:options>
<abc:option name="is-enabled" type="boolean">false</abc:option>
<abc:option name="wing-span" type="float">1.2</abc:option>
</abc:options>
Use case 2
This document is not valid for this schema because the simple type bit is wrong for the #type attribute.
<abc:options>
<abc:option name="is-enabled" type="boolean">24</abc:option>
<abc:option name="wing-span" type="float">this-is-not-a-number!</abc:option>
</abc:options>
What I have tried so far ...
Listing 3 is my attempt so far. But it is bad because I have to re-declare the #name attribute for each datum type. Is there a better solution? That is to say, one where I don't have to re-declare the #name attribute for each possible datum type.
Listing 3:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:abc="http://www.example.com"
targetNamespace="http://www.example.com"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:element name="options">
<xs:complexType>
<xs:sequence minOccurs="1" maxOccurs="unbounded">
<xs:element name="abc:option" type="option-Type"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:simpleType name="option-Datum-Type">
<xs:restriction base="xs:string">
<xs:enumeration value="boolean"/>
<xs:enumeration value="integer"/>
<xs:enumeration value="float"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="option-Type-boolean">
<xs:simpleContent>
<xs:extension base="xs:boolean">
<xs:attribute name="name" type="xs:token" use="required" />
<xs:attribute name="type" type="abc:option-Datum-Type" use="required" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="option-Type-string">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="name" type="xs:token" use="required" />
<xs:attribute name="type" type="abc:option-Datum-Type" use="required" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="option-Type-float">
<xs:simpleContent>
<xs:extension base="xs:double">
<xs:attribute name="name" type="xs:token" use="required" />
<xs:attribute name="type" type="abc:option-Datum-Type" use="required" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="option-Type">
<xs:alternative test="#type='boolean'" type="abc:option-Type-boolean"/>
<xs:alternative test="#type='string'" type="abc:option-Type-string" />
<xs:alternative test="#type='float'" type="abc:option-Type-float" />
<xs:alternative type="xs:error"/>
</xs:complexType>
</xs:schema>
If the type can only be one of the atomic types you can use xs:assert like this:
<xs:complexType name="option-Type">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="name" type="xs:token" use="required" />
<xs:attribute name="type" type="xs:string" use="required" />
<xs:assert
test="if (#type='boolean') then . castable as xs:boolean
else if (#type='float') then . castable as xs:float
else if (#type='int') then . castable as xs:int
else if (#type='string') then . castable as xs:string
else false()"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
Notes:
You don't need to declare any new type. If you want you can even also skip the declaration of the enumeration.
Using this approach you need a new line for every new possible type (you don't really need a new line but it is easy to read with every type in a different line).
You can use text() instead of . if you found it to be more clear
Notice how simply this approach would be if XPath 2.0 had an eval function similar to javascript and other languages eval function:
<xs:assert test="eval(text() || ' castable as xs:' || #type)"/>
I though an eval/parse function was going to be added to XPath 3.0 spec but I think it finally has not been added.
Unlike instance of you cannot use lists (*,+) other than ? with castable as operator. You can only use atomic types using this approach.
Cast to string string should always succed as the type is declared as xs:string.
I have this xml-Schema:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:element name="Fussballmannschaft">
<xs:complexType>
<xs:attribute name="Name" type="xs:string" />
<xs:attribute name="Stadt" type="xs:string" />
<xs:attribute name="Tabellenplatz" type="xs:string" />
<xs:element name="Spieler">
<xs:complexType>
<xs:attribute name="SpielerID" type="xs:string" />
<xs:keyref name="I_D" refer="Name" />
<xs:attribute name="Name" type="xs:string" />
<xs:element name="Torwart">
<xs:attribute name="GehealteneElfmeter" type="xs:integer" />
<xs:keyref name="ID_Torwart" refer="SpielerID" />
</xs:element>
<xs:element name="Verteidiger">
<xs:attribute name="GewonneneZweikaempfe" type="xs:integer" />
<xs:keyref name="ID_Verteidiger" refer="SpielerID" />
</xs:element>
<xs:element name="Stuermer">
<xs:attribute name="GeschosseneTore" type="xs:integer" />
<xs:keyref name="ID_Stuermer" refer="SpielerID" />
</xs:element>
</xs:complexType>
</xs:element>
</xs:complexType>
</xs:element>
</xs:schema>
and this sample:
<Fussballmannschaft Name="BVB">
<Stadt>Dortmund</Stadt>
<Tabellenplatz>3</Tabellenplatz>
<Spieler SpielerID="1">
<I_D>BVB</I_D>
<Name>Oliver</Name>
<Torwart>
<GehealteneElfmeter>20</GehealteneElfmeter>
<ID_Torwart>1</ID_Torwart>
</Torwart>
</Spieler>
<Spieler SpielerID="2">
<I_D>BVB</I_D>
<Name>Peter</Name>
<Torwart>
<GewonneneZweikaempfe>20</GewonneneZweikaempfe>
<ID_Verteidiger>2</ID_Verteidiger>
</Torwart>
</Spieler>
<Spieler SpielerID="3">
<I_D>BVB</I_D>
<Name>Paul</Name>
<Torwart>
<GeschosseneTore>20</GeschosseneTore>
<ID_Stuermer>3</ID_Stuermer>
</Torwart>
</Spieler>
</Fussballmannschaft>
But the parser says:
S4s-elt-character: Non-whitespace Characters Are Not Allowed In Schema Elements Other Than 'xs:appinfo' And 'xs:documentation'. Saw 'Dortmund'.
Do you know where the problem is?
The real reason you're getting this error,
S4s-elt-character: Non-whitespace Characters Are Not Allowed In Schema Elements Other Than 'xs:appinfo' And 'xs:documentation
is that you're attempting to validate your XML file as an XSD file.
So, fix the way you're invoking your validating parser so that you're validating your XML file against your XSD. See How to link XML to XSD using schemaLocation or noNamespaceSchemaLocation?
Additionally, there are a slew of other problems with your XSD itself. See collapsar's answer for help there.
We also had this problem. The reason was the address of the schema http:://xyz.xsd was replaced with https:://xyz.xsd. Our schema library was not able to forward to the https address via http one. So we simply changed the http adresses to https ones in the xml file.
Stadt and Tabellenplatz mustn't be xml elements but need to be attributes of the element Fussballmannschaft. This pattern repeats with the inner elements.
The schema also lacks structures to express repetition of elements (namely the Spieler element) and choices between player roles (Torwart,Verteidiger,Stuermer).
The use of the xs:keyref in the schema definition appears to be incomplete - the referenced keys are not specified as xs:key elements. In order to demonstrate this use, a new root element Fussball is defined, which should reflect the intent of the schema to formalize the notion of soccer teams. This new root element harbors the key and keyref definitions for the club name attribute and will be needed anyway as soon as multiple teams are to be represented in in a file (there must be a single root element in an xml file ).
The following pair of schema and sample passes the validation.
Schema:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:element name="Fussball">
<xs:complexType mixed="true">
<xs:sequence>
<xs:element name="Fussballmannschaft">
<xs:complexType mixed="true">
<xs:sequence>
<xs:element name="Spieler" maxOccurs="unbounded">
<xs:complexType mixed="true">
<xs:choice>
<xs:element name="Torwart">
<xs:complexType>
<xs:attribute name="GehalteneElfmeter" type="xs:integer" />
<xs:attribute name="ID_Torwart" type="xs:integer" />
</xs:complexType>
</xs:element>
<xs:element name="Verteidiger">
<xs:complexType>
<xs:attribute name="GewonneneZweikaempfe" type="xs:integer" />
<xs:attribute name="ID_Verteidiger" type="xs:integer" />
</xs:complexType>
</xs:element>
<xs:element name="Stuermer">
<xs:complexType>
<xs:attribute name="GeschosseneTore" type="xs:integer" />
<xs:attribute name="ID_Stuermer" type="xs:integer"/>
</xs:complexType>
</xs:element>
</xs:choice>
<xs:attribute name="I_D" type="xs:string" />
<xs:attribute name="SpielerID" type="xs:integer" />
<xs:attribute name="Spielername" type="xs:string" />
</xs:complexType>
</xs:element><!-- Spieler -->
</xs:sequence>
<xs:attribute name="Name" type="xs:string" />
<xs:attribute name="Stadt" type="xs:string" />
<xs:attribute name="Tabellenplatz" type="xs:string" />
</xs:complexType>
<xs:key name="k-Spieler">
<xs:selector xpath="./Spieler"/>
<xs:field xpath="#SpielerID"/>
</xs:key>
<xs:keyref name="kref-Spieler" refer="k-Spieler">
<xs:selector xpath="./Spieler/Stuermer|./Spieler/Torwart|./Spieler/Verteidiger"/>
<xs:field xpath="#ID_Stuermer|#ID_Torwart|#ID_Verteidiger"/>
</xs:keyref>
</xs:element><!-- Fussballmannschaft -->
</xs:sequence>
</xs:complexType>
<!--
A 'key' tells you how to uniquely reference an element instance - eg. one among several soccer teams.
-->
<xs:key name="k-Verein">
<xs:selector xpath="./Fussballmannschaft"/>
<xs:field xpath="#Name"/>
</xs:key>
<!--
A 'keyref' specifies that some attribute value(s) are not only constrained by their datatype but must also uniquely identify a certain element in the file - a semantic relationship is established.
-->
<xs:keyref name="kref-Verein" refer="k-Verein">
<xs:selector xpath="./Fussballmannschaft/Spieler"/>
<xs:field xpath="#I_D"/>
</xs:keyref>
</xs:element><!-- Fussball -->
</xs:schema>
XML:
<Fussball>
<Fussballmannschaft Name="BVB" Stadt="Dortmund" Tabellenplatz="3">
<Spieler SpielerID="1" I_D="BVB" Spielername="Oliver">
<Torwart GehalteneElfmeter="20" ID_Torwart="1"/>
</Spieler>
<Spieler SpielerID="2" I_D="BVB" Spielername="Peter">
<Verteidiger GewonneneZweikaempfe="20" ID_Verteidiger="2"/>
</Spieler>
<Spieler SpielerID="3" I_D="BVB" Spielername="Paul">
<Stuermer GeschosseneTore="20" ID_Stuermer="3"/>
</Spieler>
</Fussballmannschaft>
</Fussball>
References
W3C XML Schema Definition
W3C XML Schema Definition / identity constraints
SO answer on the use of key and keyref
I have this XML schema:
<xs:element name="lineinfo">
<xs:complexType>
<xs:all>
<xs:element name="done" type="xs:unsignedInt" />
</xs:all>
<xs:attribute name="id" type="xs:long" />
<xs:anyAttribute processContents="skip" />
</xs:complexType>
</xs:element>
but I want to allow any other extra element in the lineinfo tag:
<lineinfo state="assigned" id="175">
<done>4</done>
<todo>6</todo>
</lineinfo>
I tried to add <xs:any /> inside the <xs:all>, but it doesn't seem to be allowed.
I couldn't find a way to do what I wanted, so I ended up adding all "unwanted" tags in my list, with minOccurs set to 0:
<xs:element name="lineinfo">
<xs:complexType>
<xs:all>
<xs:element name="done" type="xs:unsignedInt" />
<xs:element name="todo" minOccurs="0" />
<xs:element name="error" minOccurs="0" />
</xs:all>
<xs:attribute name="id" type="xs:long" />
<xs:anyAttribute processContents="skip" />
</xs:complexType>
</xs:element>
Parent tag of <xs:any> are only choice, sequence. w3cschools #el_any
To use <xs:any> put <xs:sequence> instead of <xs:all>. w3cschools #any
else you could use xs:anyType
xs:anyType is a type, like xs:integer (though xs:anyType is special
in that it can act as a simple or complex type, and it places
essentially no restrictions on the tree that it validates -- think of
it loosely as the Schema language's analog of java.lang.Object).
A sample use would be:
<xsd:element name="value" type="xs:anyType"/>
Anyway if you want use below an example taken from w3cschools #anyattribute
SCHEMA
<xs:element name="person">
<xs:complexType>
<xs:sequence>
<xs:element name="firstname" type="xs:string"/>
<xs:element name="lastname" type="xs:string"/>
</xs:sequence>
<xs:anyAttribute/>
</xs:complexType>
</xs:element>
<xs:attribute name="gender">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:pattern value="male|female"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
XML
<person gender="female">
<firstname>Hege</firstname>
<lastname>Refsnes</lastname>
</person>
Can anyone point me as to why the unique element in my XSD is not forcing unique-ness? This should throw an error because the last ScreenResult element does not contain a unique value for the Type attribute. I should also note that I'm truly after forcing one of each Type within ScreenResults (ScreenResult is required to exist 3 times, there are 3 types of screens and I am requiring unique-ness) so if there is a better way to accomplish that, I'm all for that as well.
Thank you.
Here is my XML snippet:
<ScreenResults>
<ScreenResult Type="Screen Type A">1</ScreenResult>
<ScreenResult Type="Screen Type B">1</ScreenResult>
<ScreenResult Type="Screen Type B">2</ScreenResult>
</ScreenResults>
Here is my XSD snippet (also note that my original XSD snippets span multiple files but I have verified all of my namespaces are correct):
<xs:element name="ScreenResults" type="import:ScreenResults" minOccurs="0" maxOccurs="1">
<xs:unique name="UniqueScreenResults">
<xs:selector xpath="ScreenResult" />
<xs:field xpath="#Type" />
</xs:unique>
</xs:element>
<!--============ ScreenResults =============-->
<xs:complexType name="ScreenResults">
<xs:sequence minOccurs="1" maxOccurs="1">
<xs:element name="ScreenResult" minOccurs="3" maxOccurs="3">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="enum:ScreenResult">
<xs:attribute name="Type" type="enum:ScreenType" use="required" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
<!--============= ScreenType =============-->
<xs:simpleType name="ScreenType">
<xs:restriction base='xs:token'>
<xs:enumeration value='Screen Type A' >
<xs:annotation>
<xs:documentation>1</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value='Screen Type B' >
<xs:annotation>
<xs:documentation>2</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value='Screen Type C' >
<xs:annotation>
<xs:documentation>3</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<!--============ ScreenResult ============-->
<xs:simpleType name="ScreenResult">
<xs:restriction base='xs:token'>
<xs:enumeration value='1' >
<xs:annotation>
<xs:documentation>Positive</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value='2' >
<xs:annotation>
<xs:documentation>Negative</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value='3' >
<xs:annotation>
<xs:documentation>Not administered</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
I'm posting my solution for anyone else who runs into this problem.
Although I had asserted that all of my namespaces were correct, that was, of course the problem. All of the namespaces were correct except on the unique element itself.
I erroneously assumed that the unique element would not need to prefix a namespace as it was within the context. But that is not the case. Since I did declare a default namespace for the file, I still needed the prefix.
So my only change, and the solution, is as follows:
<xs:element name="ScreenResults" type="import:ScreenResults" minOccurs="0" maxOccurs="1">
<xs:unique name="UniqueScreenResults">
<xs:selector xpath="import:ScreenResult" />
<xs:field xpath="#Type" />
</xs:unique>
</xs:element>