Following up on this question XSLT: Copy child elements of a complex type only once, i have a problem using that template recursivlely.
Lets say i have a structure like that:
<complexType name="InvoiceType">
<xs:element name="AdressIn" type="AdressType"/>
<xs:element name="AdressOut" type="AdressType" />
<xs:element name="Partner" type="PartnerType" />
<xs:element name="Date" type="DateType"/>
</complexType>
<complexType name="AdressType">
<xs:element name="Person" type="PersonType"/>
<xs:element name="City" type="string" />
<xs:element name="Nr" type="int" />
</complexType>
<complexType name="PartnerType">
<xs:element name="Person" type="PersonType"/>
<xs:element name="Age" type="int"/>
</complexType>
<complexType name="PersonType">
<xs:element name="Name" type="string"/>
</complexType>
And this template:
<xsl:template match="xs:complexType" mode="copy">
<xsl:apply-templates select="/xs:schema/xs:complexType[#name=current()/xs:sequence/xs:element/#type]"
<xsl:copy-of copy-namespaces="no" select="."></xsl:copy-of>
</xsl:template>
I am trying to copy all referenced complexType with this template. My problem now is, PersonType
is referenced both by AdressType and PartnerType (see example). In my outputfile, this type is printed twice. (simplified example)
How can i work around that?
Thanx for any help!
What do you actually want to do?
(1) Display all the complex types in the schema document? (that's easy).
(2) Display all the global complex types that are actually referenced from somewhere?
You could do
select(//xs:complexType[#name = //xs:element/#type])
(It's not correct in the presence of namespaces, but neither is your original)
(3) Display a complex type the first time it's encountered in some kind of graph traversal, but not subsequently?
That's much harder and involves some fairly tough recursive coding.
Generally, accessing schema information from source XSD files is difficult; it gets harder the more you want to handle "any schema in the wild" rather than just a few schemas written in the way you would write them. It might be worth standing back and asking what the purpose of this exercise is.
Related
Here is an example of what I'd like to be able to do as a sample of XML (take note of the file elements):
...
<run-list>
<topic name="topic1"/>
<topic name="topic2">
<file number="2"/>
<file number="3">
/a/b/c /a/b/d /a/b/g/h/i
</file>
</topic>
</run-list>
...
The run-list element can contain any number of topic elements. The topic element may contain zero or more file elements. The file element has the number attribute (required) and may contain zero or more path strings (the list).
I can't figure out how to define a schema type to allow for the definition of the file element as described above. I need the file element to have the number attribute and I'd like to be able to specify an optional list of path values. I have been able to define simple list types for other situations, but they don't have any attributes.
I have been able to do something that is close to this, but needed to define another schema type for the paths and implement it as an element within the file element. So I'd have something like this:
...
<file number="3">
<path>/a/b/c</path>
<path>/a/b/d</path>
<path>/a/b/g/h/i</path>
</file>
...
I'd like to avoid having to define a separate schema type and element to specify the path(s) under a given file element.
Any help would be appreciated.
I think I figured it out. Here's the schema that seems to work:
<xs:complexType name="TestSpecification">
<xs:sequence>
<xs:element name="topic" type="TopicSpecification"
minOccurs="1" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="TopicSpecification">
<xs:sequence>
<xs:element name="file" type="FileSpecification" minOccurs="0"
maxOccurs="unbounded" />
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required" />
</xs:complexType>
<xs:complexType name="FileSpecification">
<xs:simpleContent>
<xs:extension base="EntityPathList">
<xs:attribute name="number" type="xs:positiveInteger" use="required" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:simpleType name="EntityPathList">
<xs:list itemType="xs:string" />
</xs:simpleType>
If anyone sees any potential problems with this, suggestions on how to improve or alternatives, please feel free to comment.
I would like to know if it is possible to validate attribute names by pattern using XML Schema. In other words, I would like to describe a set of acceptable attribute names for a given type, using a pattern (such as a regular expression).
Lets say I have the following XML data I would like to validate:
<?xml version="1.0" encoding="utf-8"?>
<root xmlns="http://mywebsite.com/myns">
<somename data-someattr1="value1"
data-someattr2="value2"/>
</root>
How can I describe that attributes of elements with name "somename" can only have attributes with name beginning by "data-"? Is this even possible?
Try something along the lines of:
<xs:simpleType name="somename">
<xs:restriction base="xs:string">
<xs:pattern value="^data-"/>
</xs:restriction>
</xs:simpleType>
The regex ^data- means "beginning with 'data-'", as you require.
EDIT:
I misunderstood the question, sorry... Here is a more relevant answer:
As I understand it, you cannot pattern match attribute names in an XSD - so there is no solution to your problem using an XSD alone. However, you may find one of the following XML schema elements helpful in constructing a solution:
XML choice (http://www.w3schools.com/schema/el_choice.asp) - so you could (possibly?) list all "data-" attribute names explicitly.
XML any (http://www.w3schools.com/schema/schema_complex_any.asp) - so you could then perform any additional validation steps via some other method.
Well, as it was said you can't validate attribute names, but you still can go different way and transform your xml to some kind of:
<root>
<element>
<data name='data-attr1' value='v1'/>
<data name='data-attr2' value='v2'/>
<data name='data-attr3' value='v3'/>
</element>
</root>
So now you can validate fake attribute name - data name='data-attr1' as well as values. Your schema might look like this:
<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema' elementFormDefault='qualified' attributeFormDefault='unqualified'>
<xs:element name='root'>
<xs:complexType>
<xs:sequence>
<xs:element name='element'>
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs='10' name='data'>
<xs:complexType>
<xs:attribute name='name' use='required'>
<xs:simpleType>
<xs:restriction base='xs:string'>
<xs:pattern value='data-.*' />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name='value' use='required' />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Take the following over simplified XSD:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="com.acme" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Widget">
<xs:complexType>
<xs:sequence>
<xs:element
minOccurs="0" name="color" nillable="true" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="WidgetColor" type="xs:string" />
</xs:schema>
Then, attempt the following:
xjc test.xsd
You should invariably get the following exception:
parsing a schema...
compiling a schema...
[ERROR] Two declarations cause a collision in the ObjectFactory class.
line 11 of file:/C:/test.xsd
[ERROR] (Related to above error) This is the other declaration.
line 7 of file:/C:/test.xsd
Failed to produce code.
Notice that There is an element name "Widget" which is a complexType and has elements named "color". There is also, at the same level as the element "Widget", an simple element named "WidgetColor".
What is more puzzling is that if you remove the attribute minOccurs="0" OR you remove the attribute nillable="true" from the "color" element sequence, xjc compiles the schema successfully.
Has anyone ever seen this problem or can suggest a solution?
Thanks,
Mike.
Well I finally figured out how to fix my problem. It lies in using a custom binding to specify a distinct class name for one of the declarations.
Content of custom-binding.xjb
<?xml version="1.0" encoding="UTF-8"?>
<bindings version="2.0" xmlns="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<bindings schemaLocation="test.xsd">
<bindings node="//xs:element[#name='WidgetColor']">
<class name="BaseWidgetColor" />
</bindings>
</bindings>
</bindings>
Operation:
C:\>xjc -b custom-binding.xjb test.xsd
parsing a schema...
compiling a schema...
acme\com\BaseWidgetColor.java
acme\com\ObjectFactory.java
acme\com\Widget.java
acme\com\package-info.java
Patience et longueur de temps valent mieux que rage et acharnement...!
I have a restriction to set on values of the element. As per the rules I want to set, following set of values are possible for my element.
<tags>
<tag>One of Audio, Video, Others.</tag>
<tag>For Audio, either Label or Record, For Video, either Studio or Producer, For Others this tag will be empty.</tag>
<tag>One of English, Spanish, French</tag>
</tags>
Now I could have set a regex pattern restriction in my XSD for a single tags element if it was plain text delimiter (,) separated values which might be
<element name="tags">
<simpleType>
<restriction base="string">
<pattern value="(Audio, (Label|Record)|Video, (Studio|Producer)|Others), (English|Spanish|French)" />
</restriction>
</simpleType>
</element>
But since I have a sequence of elements with same name tag, I am not sure it is even possible to restrict such way via XSD. I know I can restrict the values via enumeration but then I cannot group those. I want following XML to validate
<tags>
<tag>Audio</tag>
<tag>Record</tag>
<tag>English</tag>
</tags>
And following to fail validation
<tags>
<tag>Others</tag>
<tag>Record</tag>
<tag>English</tag>
</tags>
My real case is much more complex with nested restrictions, but I someone can help out in above condition, I think I can take it as a reference and solve my problem.
I don't think you can. If you have control of the schema why do you desire this specific rule set for validation? If you need this strict validation in this exact way you may need it done at the application level and not the document definition level. It appears what you really want is a way to tag different information based on certain tag "types". There really is no reason to have a list of elements all named tag, you know they are tags already from the parent elements name. Instead if you want validation based on the type of tags you should use different element types and structure your schema to validate against which types are allowed when and where. For your data this can be done using complex types and a choice model:
<xs:element name="audio">
<xs:complexType>
<xs:choice>
<xs:element name="Label" type="xs:string"/>
<xs:element name="Record" type="xs:string"/>
</xs:choice>
</xs:complexType>
</xs:element>
<xs:complexType name="generic">
<xs:choice>
<xs:element name="Studio" type="xs:string"/>
<xs:element name="Producer" type="xs:string"/>
</xs:choice>
</xs:complexType>
<xs:element name="video" type="generic"/>
<xs:element name="other" type="generic"/>
<xs:element name="tags">
<xs:complexType>
<xs:sequence>
<xs:choice>
<xs:element ref="audio"/>
<xs:element ref="video"/>
<xs:element ref="other"/>
</xs:choice>
<xs:element name="language">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="English"/>
<xs:enumeration value="Spanish"/>
<xs:enumeration value="French"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
I took liberty for Producer, Label, Studio, and Record that you would want the values for those types as well. If not, for your original case you can just use an attribute on the parent elements instead like this:
<xs:complexType name="generic">
<xs:attribute name="meta-type">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="Studio"/>
<xs:enumeration value="Producer"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
Instead of using a choice group you could use substitutionGroups but this would require each element to be derived from the same type which you may not want.
These schema's can be expanded quite easily and if you still need a generic <tag>'s list that doesn't need strict validation you could add it as part of the tags sequence definition.
Maybe someone can give you a better answer for your original requirements, but I hope this information helps.
I'm trying to build an element type that keep a list of change element type that is the base type of several other child type. I got this code :
<xs:complexType name="change_list" >
<xs:annotation>
<xs:documentation>List of changes.</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:choice minOccurs="1" maxOccurs="unbounded" >
<xs:element name="change" type="aos:change" >
<xs:annotation>
<xs:documentation>Generic or specific type of change.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="activate" type="aos:activate" >
<xs:annotation>
<xs:documentation>Change that will activate an element or do nothing if already activated.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="deactivate" type="aos:deactivate" >
<xs:annotation>
<xs:documentation>Change that will deactivate an element or do nothing if already deactivated.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="switch" type="aos:switch" >
<xs:annotation>
<xs:documentation>Change that will activate the element if deactivated or deactivate it if activated.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="transform" type="aos:transform" >
<xs:annotation>
<xs:documentation>
Change that will modify the geometric state of the element
by applying one or several geometric transformations.
</xs:documentation>
</xs:annotation>
</xs:element>
</xs:choice>
</xs:sequence>
Im' using CodeSynthesis to generate C++ code.
Now, that seems overkill because here we clearly define access to different types. I think what I want is something simpler like :
List of changes.
<xs:sequence>
<xs:choice minOccurs="1" maxOccurs="unbounded" >
<xs:element name="change" type="aos:change" >
<xs:annotation>
<xs:documentation>Generic or specific type of change.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:choice>
</xs:sequence>
Now that don't allow me to have different tags for different subtypes of changes.
So I thought maybe a good solution might be to use substitution group.
But then I would loose the ability to use the specific sub-type's attributes and elements.
Is the original solution good to do that (having a list of base type object that can get child types too)?
Dont know if you still need an answer... But the following schema does what you need.
First of all the base type and two concrete subtypes (make sure, that your base class has abstract="true" set):
<xs:complexType abstract="true" name="BaseTask">
<xs:sequence>
<xs:element name="Name" type="xs:string" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="ConcreteTask1">
<xs:complexContent>
<xs:extension base="BaseTask">
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="ConcreteTask2">
<xs:complexContent>
<xs:extension base="BaseTask">
<xs:sequence>
<xs:element name="Description" type="xs:string" />
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
Then adding a list that holds elements that are subtypes of BaseTask:
<xs:element name="TaskList">
<xs:complexType>
<xs:sequence>
<xs:element name="Tasks" minOccurs="0" maxOccurs="unbounded" type="BaseTask" />
</xs:sequence>
</xs:complexType>
</xs:element>
The xml then looks like this:
<TaskList>
<Tasks xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ConcreteTask1">
<Name>Foo1</Name>
</Tasks>
<Tasks xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ConcreteTask2">
<Name>Foo2</Name>
<Description>Test</Description>
</Tasks>
</TaskList>
What you want is not possible in xml-schema. You can extend (or restrict) a defined type but then this is a new type. Subtyping polymorphism (inclusion polymorphism) doesn't exist in xml-schema.
It sounds like what you want is a list of changes, but you also want the type of change recorded in the list (activate, switch, etc).
What I would do is make a simple element called ChangeType element that would have a "type" attribute whose data type would be another element, ChangeTypeType which would be an enum of your valid changed types. For example:
<element name="ChangeList" type="ChangeListType"/>
<complexType name="ChangeListType">
<annotation>
<documentation>
A list of changes
</documentation>
</annotation>
<sequence>
<element name="change" type="ChangeType" minOccurs="1" maxOccurs="unbounded">
<annotation>
<documentation>
A change event
</documentation>
</annotation>
</element>
</sequence>
</complexType>
<complexType name="ChangeType">
<annotation>
<documentation>
A change unit
</documentation>
</annotation>
<attribute ref="typeOfChange" use="required"/>
</complexType>
<attribute name="typeOfChange" type="ChangeTypeType">
<annotation>
<documentation>
The kind of change
</documentation>
</annotation>
</attribute>
<simpleType name="ChangeTypeType">
<annotation>
<documentation>
Describes the types of allowed changes
</documentation>
</annotation>
<restriction base="token">
<enumeration value="activate"/>
<enumeration value="activate"/>
<enumeration value="switch"/>
<enumeration value="transform"/>
</restriction>
</simpleType>
This would give you an XML document like:
<ChangeList>
<change typeOfChange="activate/>
<change typeOfChange="switch/>
<change typeOfChange="transform/>
</ChangeList>