Ensure child element cannot exist without parent Using Xsd - xsd

I am facing issues in trying to get this schema validation inside xsd.
Valid case
<root>
<groups>
<group/>
</groups>
</root>
Valid case
<root>
<groups/>
</root>
Invalid case
<root>
<group/>
</root>
How to ensure that a particular child element can only exist under some parent, not alone in xml through xsd?
In this e.g.
group cannot exist alone, but can exist when groups is parent...
Someone replied that do not make group element global i.e contain it within groups element...
But there can be a case,
where group is not the direct child of parent.
e.g
valid case
<groups>
<class>
<group>
</class>
</groups>
what should be done in that cases...as class needs to refer to group too...

Based on your question, it sounds to me more like you want class and group to be interchangeable. For that, you want to use a recursive schema element, like so...
<xsd:element name="Groups">
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="BranchType"/>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="BranchType">
<xsd:sequence>
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element name="Class" type="BranchType" minOccurs="0" maxOccurs="1"/>
<xsd:element name="Group" minOccurs="0" maxOccurs="1"/>
</xsd:choice>
</xsd:sequence>
</xsd:complexType>
We basically define a BranchType that can contain any mix of Group elements or itself (via the Class element). Then we define the top level Groups as type BranchType. I use a sequence of choice so that the Class and Group elements can appear in any order, any number of times, to any level of nesting.

When you don't want an element to show by itself, it must be declared inside the complex type that defines its parent.
Below is an easy "fix", generated by a tool; when learning, it may prove a good way to jumpstart XSDs, at least to get the syntax right...
UPDATE: If you keep adding content, you need to update the schema. If the element is not global, then the solution is the same: definition within its parent. If the content model is the same, then define that as a global type, and refer it in the definition of the element (in this case it would be instead of anyType).
<?xml version="1.0" encoding="utf-8"?>
<!--XML Schema generated by QTAssistant/XML Schema Refactoring (XSR) Module (http://www.paschidev.com)-->
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element name="groups">
<xs:complexType>
<xs:sequence minOccurs="0">
<xs:element name="group" type="xs:anyType" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="groups">
<xs:complexType>
<xs:sequence>
<xs:element name="class">
<xs:complexType>
<xs:sequence>
<xs:element name="group" type="xs:anyType" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

Related

jaxb generated class for xsd:group

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.

XSD/JAXB: Sequence of multiple elements bounded by elements with the same name

My model element may contain several child elements of different types. For each type, only 0 or 1 child elements may be present. The order of these elements is defined, i.e. all elements of type A come before B etc. My model class, generated by JAXB, should therefore have a separate getter/setter property for each type of child element.
What complicates things is the one exception to the above rule: At the beginning and near the end of the list of child elements there may each appear 0 or 1 elements of type X, and these elements both have the same name.
Here's a slightly simplified version of my current real life XSD type:
<xs:complexType name="Activity">
<xs:sequence>
<xs:element name="log" type="DiagnosticLogMessage" minOccurs="0" maxOccurs="1" />
<xs:element name="inputs" type="Mappings" minOccurs="0" maxOccurs="1" />
<xs:element name="outputs" type="Mappings" minOccurs="0" maxOccurs="1" />
<xs:element name="log" type="DiagnosticLogMessage" minOccurs="0" maxOccurs="1" />
<xs:element name="to" type="DirectConnection" minOccurs="0" maxOccurs="1" />
</xs:sequence>
</xs:complexType>
"log" is the problematic element. With the above type definition, "to" correctly gets its own property, but the remaining elements go into a list named "logsAndInputsAndOutputs". If I rename the two "log" elements to "logBefore" and "logAfter", each elements gets its own property, so clearly the problem is that JAXB cannot differentiate between the two "log"s.
I understand that the XSD itself is not really exact: It allows a single child element of type "log", in which case it's undefined if this is to be considered the "before" or the "after" element. In my current (manually written) reader class I have explicit code to detect this case and interpret a single "log" element as the "before" element.
I'm looking for a way to tell JAXB to treat the two "log" elements differently, either via xjb mappings or possibly with a more specific XSD.
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
Below is how you could handle this use case by leveraging MOXy's #XmlPath extension.
XML Schema (schema.xsd)
Here is an XML schema based on the fragment you have provided in your question.
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="urn:forum17408865" xmlns="urn:forum17408865"
elementFormDefault="qualified">
<xs:element name="foo">
<xs:complexType>
<xs:sequence>
<xs:element name="bar" type="Activity"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="Activity">
<xs:sequence>
<xs:element name="log" type="DiagnosticLogMessage"
minOccurs="0" maxOccurs="1" />
<xs:element name="inputs" type="Mappings" minOccurs="0"
maxOccurs="1" />
<xs:element name="outputs" type="Mappings" minOccurs="0"
maxOccurs="1" />
<xs:element name="log" type="DiagnosticLogMessage"
minOccurs="0" maxOccurs="1" />
<xs:element name="to" type="DirectConnection" minOccurs="0"
maxOccurs="1" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="DiagnosticLogMessage" />
<xs:complexType name="Mappings" />
<xs:complexType name="DirectConnection" />
</xs:schema>
Activity
MOXy has an #XmlPath extension that allows you to map to an XML element based on its position. This class can't be generated from the XML schema so we will create it ourselves.
package forum17408865;
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlPath;
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(propOrder={"log1", "inputs", "outputs", "log2", "to"})
public class Activity {
#XmlPath("log[1]")
private DiagnosticLogMessage log1;
private Mappings inputs;
private Mappings outputs;
#XmlPath("log[2]")
private DiagnosticLogMessage log2;
private DirectConnection to;
}
binding.xml
To have JAXB use the class we created manually we will leverage a JAXB bindings file.
<jxb:bindings xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb" version="2.1">
<jxb:bindings schemaLocation="schema.xsd">
<jxb:bindings node="//xs:complexType[#name='Activity']">
<jxb:class ref="forum17408865.Activity" />
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>
XJC Call
Below is the XJC call that leverages the bindings file. Note how we also needed to use the -nv flag to disable schema validation.
xjc -nv -b binding.xml schema.xs
For More Information
http://blog.bdoughan.com/2010/07/xpath-based-mapping.html
http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html

XSD: specify a choice must have at least one from a list but no more than one of each

This has been driving me mad for hours. I've read every relevant XSD question on SO and the rest of the Internet it seems and still the answer eludes me.
I need an XML schema that requires at least one of list of elements be present, but each element may appear only 0 or 1 times.
This is similar to this question:
XML schema construct for "any one or more of these elements but must be at least one"
but I was unable to constrain the upper limit: I am apparently using maxOccursincorrectly.
Here's where I left off with my schema:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:complexType name="Selects">
<xs:sequence minOccurs="2" maxOccurs="4">
<xs:choice>
<xs:element name="aaa" minOccurs="1" maxOccurs="1"/>
<xs:element name="bbb" minOccurs="1" maxOccurs="1"/>
<xs:element name="ccc" minOccurs="1" maxOccurs="1"/>
<xs:element name="ddd" minOccurs="1" maxOccurs="1"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
<xs:element name="baseElement">
<xs:complexType>
<xs:sequence>
<xs:element name="MyChoice" type="Selects"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
I've tried the minOccurs and maxOccurs on the choice and the element with no luck. Here is XML that validates, though I don't want it to:
<?xml version="1.0" encoding="UTF-8"?>
<baseElement xsi:noNamespaceSchemaLocation="myTest.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<MyChoice>
<ddd/>
<ddd/>
</MyChoice>
</baseElement>
Here's an example of what I would like, if possible:
<?xml version="1.0" encoding="UTF-8"?>
<baseElement xsi:noNamespaceSchemaLocation="myTest.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<MyChoice>
<ddd/>
<aaa/>
<ccc/>
</MyChoice>
</baseElement>
I would like it to complain about the multiple ddd elements but allow any or all of the others in any order. I get an error if I only have one element under MyChoice so at least something works.
What am I doing wrong? How do I prevent multiple of the same element from validating?
UPDATE
This was my solution (from comments on answer below):
Actually, xs:all did the trick. I swapped the choice for all and added minOccurs="0" maxOccurs="1" to each element. With xs:all, minOccurs must be either 0 or 1 and maxOccurs must be 1. Thanks for your help - I'm good to go now!
Just move the <xs:sequence minOccurs="2" maxOccurs="4"> from around the choice to the point where you want to use it further down. (you can also remove the min/max occurs = 1 as this is what xs:choice does)
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:complexType name="Selects">
<xs:choice>
<xs:element name="aaa" />
<xs:element name="bbb" />
<xs:element name="ccc" />
<xs:element name="ddd" />
</xs:choice>
</xs:complexType>
<xs:element name="baseElement">
<xs:complexType>
<xs:sequence minOccurs="2" maxOccurs="4">
<xs:element name="MyChoice" type="Selects" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
This validates the following:
<baseElement xsi:noNamespaceSchemaLocation="myTest.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<MyChoice>
<bbb></bbb>
</MyChoice>
<MyChoice>
<ccc></ccc>
</MyChoice>
</baseElement>
UPDATE
I think you are reaching the limit of what you can achieve with XSD. I can't see any way you can do this other than by defining a "version" of the MyChoice type for every single combination possible (which will then need different names MyChoice1, MyChoice2 etc)
You can also use xs:all
<xs:complexType name="Selects">
<xs:all minOccurs=2 maxOccurs=4>
<xs:element name="aaa" />
<xs:element name="bbb" />
<xs:element name="ccc" />
<xs:element name="ddd" />
</xs:all>
</xs:complexType>
but this will not prevent you from having four <ddd/>'s

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>

Are circular groups allowed by XSD schema?

For this xml:
<elem1 xmlns="http://www.fixprotocol.org/ns/fast/t/1.0">
<elem2>
<elem2/>
</elem2>
</elem1>
I have this schema, which seems to validate fine against w3 schema validation service, and the schema validates the above XML just fine. Sadly, xsd.exe and some other tools report it to be an error. Is that correct? Are circular group refs dissallowed by XML schema? Thanks!
Update: The schema is not mine, can't change it :(
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.fixprotocol.org/ns/fast/t/1.0" xmlns:t="http://www.fixprotocol.org/ns/fast/t/1.0">
<xs:element name="elem1">
<xs:complexType>
<xs:group ref="t:grp1" />
</xs:complexType>
</xs:element>
<xs:group name="grp1">
<xs:sequence>
<xs:group ref="t:grp2" />
</xs:sequence>
</xs:group>
<xs:group name="grp2">
<xs:sequence>
<xs:element minOccurs="0" name="elem2">
<xs:complexType>
<xs:group ref="t:grp1" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:group>
</xs:schema>
It's a legal scheme. Problem is that xsd is trying to traverse all dependencies. The MS version preprocesses scheme and expands all groups. Because of the cyclic dependency such expansion would be infinite so it quits with an error. With the Mono version there are two probable scenarios:
It tries to traverse dependency tree
and ends up in an infinite loop.
It tries to expand all groups and
ends up in an infinite loop.
That is just my guess. I never saw actual source codes of Mono xsd.
This question is being linked with many recent questions that talk about the same problem: circular groups, and Microsoft's xsd.exe, hence I think it should be answered, even though it is quite "old".
The confusion is caused by what qualifies as a circular group. According to section 3.8.6 of the XSD spec:
"Circular groups are disallowed. That is, within the {particles} of a
group there must not be at any depth a particle whose {term} is the
group itself."
Based on the above, your example is not a circular group, since the group itself does not rely on itself as a particle. Your schema is valid.
This is a circular group:
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns="http://www.fixprotocol.org/ns/fast/t/1.0" attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://www.fixprotocol.org/ns/fast/t/1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="elem1">
<xsd:complexType>
<xsd:group ref="grp1"/>
</xsd:complexType>
</xsd:element>
<xsd:group name="grp1">
<xsd:sequence>
<xsd:choice>
<xsd:group ref="grp1"/>
</xsd:choice>
</xsd:sequence>
</xsd:group>
</xsd:schema>
One cannot rewrite a true circular group. However, your example can be rewritten in a couple of ways: the schema below shows an equivalent content model, based on recursive complex types.
<?xml version="1.0" encoding="utf-8" ?>
<!-- XML Schema generated by QTAssistant/XSD Module (http://www.paschidev.com) -->
<xsd:schema xmlns="http://www.fixprotocol.org/ns/fast/t/1.0" attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://www.fixprotocol.org/ns/fast/t/1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:annotation>
<xsd:documentation xmlns="">Generated from "Set1" under "Release2"</xsd:documentation>
</xsd:annotation>
<xsd:complexType name="grp1">
<xsd:sequence>
<xsd:element minOccurs="0" name="elem2" type="grp1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="elem1" type="grp1"/>
</xsd:schema>
It is also "entertaining" to see that the following schema actually works with xsd.exe:
<?xml version="1.0" encoding="utf-8"?>
<!--XML Schema generated by QTAssistant/XML Schema Refactoring (XSR) Module (http://www.paschidev.com)-->
<xsd:schema xmlns="http://www.fixprotocol.org/ns/fast/t/1.0" attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://www.fixprotocol.org/ns/fast/t/1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:annotation>
<xsd:documentation xmlns="">Generated from "Set1" under "Release2"</xsd:documentation>
</xsd:annotation>
<xsd:element name="elem1">
<xsd:complexType>
<xsd:group ref="grp1"/>
</xsd:complexType>
</xsd:element>
<xsd:group name="grp1">
<xsd:sequence>
<xsd:element minOccurs="0" name="elem2">
<xsd:complexType>
<xsd:group ref="grp1"/>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:group>
</xsd:schema>
From an XML instance perspective, all three valid schemas are equivalent.
The issue is probably that the tools you are using don't support all possibilities supported by the XML schema spec. Certainly xsd.exe doesn't support everything. The spec is gigantic and it isn't worth providing mappings from everything it supports into a programming language, particularly when some things just don't map very well.
To work around this, you could try to create a set of C# classes that mimic the xml you want to generate and then run xsd.exe on those classes to generate an xsd. There is probably some other XML schema construct that supports what you want.
I don't know about groups but XSD.exe supports circular elements:
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Class1" nillable="true" type="Class1" />
<xs:complexType name="Class1">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" name="Name" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="1" name="child" type="Class1" />
</xs:sequence>
</xs:complexType>
</xs:schema>

Resources