Is it possible for extended types to be used interchangeably with their base element, or vice versa?
For example, I've got a WSDL, which specifies a few elements:
<s:complexType name="Original">
<s:sequence>
<s:element name="basic" type="s:string"/>
</s:sequence>
</s:complexType>
<s:complexType name="Extended">
<s:complexContent mixed="false">
<s:extension base="tns:Original">
<s:sequence>
<s:element name="extra" type="s:string"/>
</s:sequence>
</s:extension>
</s:complexContent>
</s:complexType>
Is it ever possible for either of these elements to be used in place of the other?
Of course, different applications/implementations will accept different things, so this question is mostly about whether or not it is correct, and follows standards.
To further extend my original example, if the WSDL specified that a message contained an Original, like so:
<s:complexType name="Other">
<s:sequence>
<s:element name="Original" type="tns:Original"/>
</s:sequence>
</s:complexType>
Would it be possible to give it an Extended, while still following conventions? Or what about the other way?
What if you tried something a little hacky, such as:
<Original xsi:type="Extended">
<basic>foo</basic>
<extra>bar</extra>
</Original>
Thanks!
What you have described is perfectly valid. In fact you have to add the 'block' attribute in order to prevent it.
So where you have a reference to 'Original' you could use xsi:type='Extended' in the XML document and use the definition defined of 'Extended'. However the converse is not true, in your example an element of type 'Extended' can not contain just an 'Original' type.
<?xml version="1.0" encoding="utf-8" ?>
<!--Created with Liquid XML 2017 Developer Bundle Edition 15.0.0.6978 (https://www.liquid-technologies.com)-->
<s:schema elementFormDefault="qualified" xmlns:s="http://www.w3.org/2001/XMLSchema">
<s:element name="Root">
<s:complexType>
<s:sequence>
<s:element name="OriginalElm" type="Original" minOccurs="0" maxOccurs="unbounded" />
<s:element name="ExtendedElm" type="Extended" minOccurs="0" maxOccurs="unbounded" />
<s:element name="OriginalBlocked" type="Original" block="extension" />
</s:sequence>
</s:complexType>
</s:element>
<s:complexType name="Original">
<s:sequence>
<s:element name="basic" type="s:string" />
</s:sequence>
</s:complexType>
<s:complexType name="Extended">
<s:complexContent mixed="false">
<s:extension base="Original">
<s:sequence>
<s:element name="extra" type="s:string" />
</s:sequence>
</s:extension>
</s:complexContent>
</s:complexType>
</s:schema>
The following XML is valid against the schema
<?xml version="1.0" encoding="utf-8"?>
<!-- Created with Liquid XML 2017 Developer Bundle Edition 15.0.0.6978 (https://www.liquid-technologies.com) -->
<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="D:\Development2017\Liquid\Applications\XmlStudio\Tests\UserSamples\xsiType\XSDFile3.xsd">
<OriginalElm>
<basic>string</basic>
</OriginalElm>
<OriginalElm xsi:type="Extended">
<basic>string</basic>
<extra>string</extra>
</OriginalElm>
<ExtendedElm>
<basic>string</basic>
<extra>string</extra>
</ExtendedElm>
<OriginalBlocked>
<basic>string</basic>
</OriginalBlocked>
</Root>
However this version of 'OriginalBlocked' is not valid as it can not be extended due to the 'block' attribute.
<OriginalBlocked xsi:type="Extended">
<basic>INVALID</basic>
<extra>INVALID</extra>
</OriginalBlocked>
A note on compatibility.
Most Validating XML parsers will treat these correctly (I tested on Xerces & .Net) however most client applications will not be looking out for the xsi:type attribute. Its most likely that they will just ignore this additional data, but that's down to how they are coded.
Another small point, its a good convention to name complexTypes and simpleTypes in the form XxxxType. The parser is fine with elements attributes and types all having the same name, but it gets confusing to us!
Related
I am working on an application that uses XJC to generate Java POJOs from XSDs. There are dozens of schemas, and that number will grow. The application also needs to be able to handle different versions of the same schema, which means that I will have multiple schemas defining common types. I am trying to customize the bindings so that certain core types implement a common interface. The Inheritance plugin of JAXB2 Basics seems to do what I need, but I can't seem to nail the right syntax.
Here is the relevant part of my schema:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:my="http://example.com/core"
targetNamespace="http://example.com/core"
xmlns:xml="http://www.w3.org/XML/1998/namespace">
...
<xs:complexType name="addressType">
<xs:sequence>
<xs:element name="Address" type="xs:string"/>
<xs:element name="City" type="xs:string"/>
<xs:element name="Province" type="xs:string"/>
<xs:element name="Country" type="xs:string"/>
<xs:element name="County" type="xs:string" minOccurs="0"/>
<xs:element name="PostalCode" type="xs:string"/>
</xs:sequence>
</xs:complexType>
...
</xs:schema>
... and this is what my custom binding file looks like:
<?xml version="1.0"?>
<jaxb:bindings
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance"
xmlns:my="http://example.com/core"
jaxb:extensionBindingPrefixes="inheritance"
version="2.1">
<jaxb:bindings scd="x-schema::my" xmlns:my="http://example.com/core">
<jaxb:globalBindings localScoping="toplevel">
<jaxb:serializable/>
<xjc:simple/>
</jaxb:globalBindings>
<jaxb:bindings scd="/type::my:addressType">
<inheritance:implements>com.mysite.validator.ValidatableAddress</inheritance:implements>
<!--<xjc:superInterface name="com.mysite.validator.ValidatableAddress"/>-->
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
I'm using the scd approach, because in all the "traditional" binding examples that show how to use the inheritence plugin, schemaLocation is specified. I want to avoid having to specify schemaLocation because of our large (and growing) number of schemas. I don't want to have to change the binding file every time we add a new schema. So, scd seems like it will satisfy this requirement.
However when I run the build using the above binding, I get this:
[xjc] [ERROR] cvc-elt.1: Cannot find the declaration of element 'inheritance:implements'.
[xjc] line 18 of file:/dev/workspace/my_app/etc/schemas/bindings-common.xml
[xjc] failure in the XJC task. Use the Ant -verbose switch for more details
[xjc] classLoader = java.net.URLClassLoader#ebcdbb
[xjc] SharedSecrets.getJavaNetAccess()=java.net.URLClassLoader$7#14562c5
If I comment out the inheritance:implements line and uncomment the xjc:superInterface line, the error goes away and the build completes successfully, but my AddressType classes don't implement the ValidatableAddress type.
Can the inheritence plugin be used with scd? Can xjc:superInterface be limited to only certain elements?
Cheers.
Author of jaxb2-basics here.
See this issue in XJC. In short, XJC for some reason does not allow custom/vendor customization elements in SCD bindings.
inheritance:implements is such customization element.
So no, this does not work due a problem in XJC.
I personally bind via schemaLocation and XPath but use a "virtual" schema location URI and rewrite it via catalogs.
SCD would have been a much better choice (you're absolutely right here) but it just does not work.
Update on virtual schema location and catalogs.
Here's an example of binding which customizes some complex type:
<jaxb:bindings
schemaLocation="http://schemas.opengis.net/wps/2.0/wpsCommon.xsd"
node="/xs:schema">
<jaxb:bindings node="xs:element[#name='Data']/xs:complexType">
<wildcard:lax/>
</jaxb:bindings>
</jaxb:bindings>
It is bound via schemaLocation and XPath. The schemaLocation is an existing URL, but in the build it is rewritten via catalog into the resource inside a Maven artifact:
REWRITE_SYSTEM "http://schemas.opengis.net" "maven:org.jvnet.ogc:ogc-schemas:jar::!/ogc"
So basically http://schemas.opengis.net/wps/2.0/wpsCommon.xsd will be loaded from the ogc-schema.jar!/ogc/wps/2.0/wpsCommon.xsd.
Using maven-jaxb2-plugin you can refer to binding files inside Maven artifacts as well:
<binding>
<dependencyResource>
<groupId>${project.groupId}</groupId>
<artifactId>ows-v_2_0</artifactId>
<resource>ows-v_2_0.jsonix.xjb</resource>
<version>${project.version}</version>
</dependencyResource>
</binding>
So, in combination, it allows writing binding files once and reuse them across modules.
But this was all a huge pain to figure out. I did it for the ogc-schemas project which is now some 50 heavily interconnected schemas. I heavily suffer from XJC drawbacks and issues, but this is the best possible at the moment. I even thought about forking and patching XJC, but this is far of effort limits I can afford.
So I've ended up with a number of mindblogging workarounds which somehow do the job at the end of the day.
Thanks to lexicore for the prompt and detailed answers. However that approach wasn't working for me, so I ended up with the following solution...
Because I am using Ant to invoke XJC, I ended up leveraging Ant's <copy filtering="true"...> capabilities to dynamically generate the binding file.
Here is my binding "template" file (bindings-common.xml):
<?xml version="1.0"?>
<jaxb:bindings
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance"
xmlns:my="http://http://example.com/core"
jaxb:extensionBindingPrefixes="inheritance"
version="2.1">
<jaxb:bindings>
<jaxb:globalBindings localScoping="toplevel">
<jaxb:serializable/>
<xjc:simple/>
</jaxb:globalBindings>
</jaxb:bindings>
<jaxb:bindings
schemaLocation="#bindingSchema#"
node="/xs:schema">
<jaxb:bindings node="//xs:complexType[#name='addressType']">
<inheritance:implements>com.example.validator.ValidatableAddress</inheritance:implements>
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
Note this line:
<jaxb:bindings
schemaLocation="#bindingSchema#"
node="/xs:schema">
This variable will get populated by Ant for each of the schemas that I am processing:
<property name="jaxb.binding.template" value="../etc/form-schemas/bindings-common.xml"/>
<property name="jaxb.binding.file" value="${jaxb.src.dir}/bindings-common${schema.version}.xml"/>
<echo message="Filtering ${jaxb.binding.file} using template ${jaxb.binding.template}"/>
<copy file="${jaxb.binding.template}"
tofile="${jaxb.binding.file}"
filtering="true">
<filterset>
<filter token="bindingSchema" value="../../etc/form-schemas/${schema.version}/common.xsd"/>
</filterset>
</copy>
<xjc destdir="${jaxb.src.dir}"
extension="true"
schema="${schema.file}"
package="${package}"
binding="${jaxb.binding.file}">
<arg value="-episode"/>
<arg value="${jaxb.src.dir}/common${schema.version}.episode"/>
<arg line="-Xinheritance"/>
<!-- Plugins -->
<classpath>
<fileset dir="../build-libs/">
<!-- JAXB2 Basics library -->
<include name="jaxb2-basics-0.6.4.jar"/>
<!-- JAXB2 Basics library dependencies -->
<include name="jaxb2-basics-runtime-0.6.4.jar"/>
<include name="jaxb2-basics-tools-0.6.4.jar"/>
<include name="javaparser-1.0.8.jar"/>
<include name="commons-beanutils-*.jar"/>
<include name="commons-lang-*.jar"/>
<include name="commons-logging-*.jar"/>
</fileset>
</classpath>
</xjc>
</target>
Hopefully this will help future generations of JAXB victims.
I'm creating a geopositioning application and we intent to use KML as our import/export data scructure.
We need to store extra information on field definitions, but I'm having trouble understant how to use KML SimpleFieldExtension (in fact my problem is understant XML Schema and validation).
The Google KML tutorial https://developers.google.com/kml/documentation/extendeddata doesn't teach how to do it.
I understand that SimpleFieldExtension is an abstract element and there is no concrect element in the KML specfication.
<element name="SimpleFieldExtension" abstract="true"/>
So I need to extend it and create my own, rigth?
I would like to do something like this:
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
<Schema name="mySchemaName" id="mySchemaId">
<SimpleField type="xsd:int" name="myValue">
<displayName>MyValue</displayName>
<mySimpleFieldExtension>
<someExtraInfo>...</someExtraInfo>
<otherExtraInfo>...</otherExtraInfo>
</mySimpleFieldExtension>
</SimpleField>
</Schema>
<!-- Some placemarks with myValue fields -->
</Document>
</kml>
When I was trying to figure this out, I came with the impression that I need to create a .xsd file with my own mySimpleFieldExtension, and some how points the .kml file to it. But I'm not sure if that is the right path.
<element name="mySimpleFieldExtension" substitutionGroup="kml:SimpleFieldExtension"/>
Can some one give me an example? Thank you in advance.
I'm using http://www.kmlvalidator.com/ to check my files.
If you want to create SimpleFieldExtension elements and validate it then you will need to create an XML Schema (.xsd) and refer that file in your KML documents.
Example XML Schema with KML extension:
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:kml="http://www.opengis.net/kml/2.2"
xmlns:ext="http://myextension"
targetNamespace="http://myextension"
elementFormDefault="qualified"
version="2.2.0">
<import namespace="http://www.opengis.net/kml/2.2"
schemaLocation="http://schemas.opengis.net/kml/2.2.0/ogckml22.xsd" />
<element name="SimpleMetadata" type="ext:SimpleMetadataType"
substitutionGroup="kml:SimpleFieldExtension"/>
<complexType name="SimpleMetadataType" final="#all">
<sequence>
<element name="description" type="string"/>
<element name="observedProperty">
<complexType>
<simpleContent>
<extension base="string">
<attribute name="type" type="string" use="required"/>
</extension>
</simpleContent>
</complexType>
</element>
<any namespace="##other" processContents="lax" minOccurs="0"
maxOccurs="unbounded"/>
</sequence>
</complexType>
</schema>
Here's KML document:
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ext="http://myextension"
xsi:schemaLocation="http://myextension ext.xsd
http://www.opengis.net/kml/2.2 http://schemas.opengis.net/kml/2.2.0/ogckml22.xsd">
<Document>
<Schema id="SensorTypesId" name="SensorTypes">
<SimpleField name="model" type="string"/>
<SimpleField name="reason" type="string"/>
<SimpleField name="speed" type="double">
<ext:SimpleMetadata>
<ext:description>this is the true air speed of a given
aircraft in meters per second</ext:description>
<ext:observedProperty type="urn:ogc:def:phenomenon:OGC:speed" />
</ext:SimpleMetadata>
</SimpleField>
</Schema>
...
A proposed example of a SimpleFieldExtension and discussion can be found here.
Note that http://www.kmlvalidator.com/ checks the strict KML specification and doesn't check KML extensions such as Google's KML extensions so you won't be able to validate custom extensions either.
You can validate such a KML document using the XML Validator which is a standalone command-line validator.
You'll need to add the namespace definition in the XML Validator ns.map config file:
http://myextension=${XV_HOME}/schemas/ext.xsd
or absolute path like this:
http://myextension=C:/myPath/ext.xsd
Even though the SimpleFieldExtension is supported by the KML standard, adding a custom SimpleFieldExtension through a custom XML Schema requires more testing to verify it doesn't cause problems to applications using it especially if you plan to share your KML outside your organization. Applications like Google Earth will simply ignore your extensions so only use extensions when you absolutely must.
I've made a simple UI definition language for a project and now want to create a schema, for ease of validation. Unfortunately, my XSD skills are quite rusty, and I find myself trying to so something that I'm not even certain is possible.
The UI is made up of "blocks" which can be positioned in relation to one another. In order to simplify the most common use cases, I'd like the referencing attribute to be able to contain any of the strings parent, previous, or next. In order to be as flexible as possible, I'd also like it to be able to point to any element with an ID.
In other words, I'd like the following to be valid:
<ui>
<block id="foo"/>
<block/>
<block anchor="previous"/>
<block anchor="#foo"/>
</ui>
How can I describe this in XSD?
As it turns out, XSD contains a feature which does exactly this — combines two or more types — and I had simply missed it. A union creates a type whose lexical space covers the lexical spaces of all of its member types (in other words, it can contain a value matching any of its subtypes).
With the caveat that IDREFs cannot contain a leading # (it's a direct reference to an ID, not a fragment identifier for a URL), the following schema will validate the example XML. The interesting bits are AnchorType and TreeReferenceType.
<schema targetNamespace="urn:x-ample:ui" elementFormDefault="qualified" xmlns="http://www.w3.org/2001/XMLSchema" xmlns:ui="urn:x-ample:ui">
<element name="ui" type="ui:UIType"/>
<complexType name="UIType">
<sequence>
<element minOccurs="1" maxOccurs="unbounded" name="block" type="ui:BlockType"/>
</sequence>
</complexType>
<complexType name="BlockType">
<attribute use="optional" name="id" type="ID"/>
<attribute name="anchor" type="ui:AnchorType"/>
</complexType>
<simpleType name="AnchorType">
<union memberTypes="ui:TreeReferenceType IDREF"/>
</simpleType>
<simpleType name="TreeReferenceType">
<restriction base="string">
<enumeration value="parent"/>
<enumeration value="previous"/>
<enumeration value="next"/>
</restriction>
</simpleType>
</schema>
SDL Tridion uses XML schema definitions to define content stored in Tridion components. XSD can use restrictions/facets or indicators to restrict what's valid for XML nodes.
Chris Summers found some of these accidentally in training, specifically that we can set minOccurs and maxOccurs indicators in SDL Tridion 2011 as in:
<xsd:element name="someField" minOccurs="2" maxOccurs="5" type="xsd:normalizedString">
Andrey Marchuk mentions additional options in the same post:
Indicators
MaxValue
MinValue
Restrictions
FractionDigits
MaxLength
MinLength
Pattern
TotalDigits
Btw, are these XSD-specific?
IsMaxValueExclusive
IsMinValueExclusive
How would I get the *restrictions into the following sample Tridion schema (source)?*
<xsd:schema xmlns="http://createandbreak.net/schema/example" xmlns:tcmi="http://www.tridion.com/ContentManager/5.0/Instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://createandbreak.net/schema/example">
<xsd:import namespace="http://www.tridion.com/ContentManager/5.0/Instance"></xsd:import>
<xsd:annotation>
<xsd:appinfo>
<tcm:Labels xmlns:tcm="http://www.tridion.com/ContentManager/5.0">
<tcm:Label ElementName="someField" Metadata="false">someField</tcm:Label>
</tcm:Labels>
</xsd:appinfo>
</xsd:annotation>
<xsd:element name="Content">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="someField" minOccurs="2" maxOccurs="5" type="xsd:normalizedString">
<xsd:annotation>
<xsd:appinfo>
<tcm:ExtensionXml xmlns:tcm="http://www.tridion.com/ContentManager/5.0"></tcm:ExtensionXml>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
To take an example from W3Schools, this would be a non-Tridion XSD restricting a field to 5 digits using a regular expression:
<xs:element name="prodid">
<xs:simpleType>
<xs:restriction base="xs:integer">
<xs:pattern value="[0-9][0-9][0-9][0-9][0-9]"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
I tried changing the xs namespace to xsd but I'm not sure where XSD restrictions would go in the (Tridion) schema.
I believe the XS and XSD is somewhat irrelevant here. Both are actually namespace prefixes which refer to the same namespace. This is described in this post.
If you look at a sample from the site you quoted (http://www.w3schools.com/schema/default.asp) you will see that the xs namespace prefix refers to http://www.w3.org/2001/XMLSchema which is the same as xsd in the Tridion schema.
E.g.
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
therefore xsd is the same as xs.
Or am I completely missing your point?
If you are just looking on how to apply restrictions, this comes from the SDL Tridion docs (here but requires password):
<xsd:element name="NumberFieldWithMultipleFacets">
<xsd:simpleType>
<xsd:restriction base="xsd:decimal">
<xsd:totalDigits value="4"/>
<xsd:fractionDigits value="2"/>
<xsd:minInclusive value="10"/>
<xsd:maxInclusive value="20"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
If you are looking for a list of the possible facets in Xml Schema, then you need to look here. Perhaps then it's a simple matter to check which of these are respected/supported by Tridion
I still miss xsd:ID for example, works in WebForms (yes, from version 1.0), but not in the latest SDL Tridion GUI (except 2013, not tested).
I would like all valid xsd's to work in the Tridion GUI.
And for example, that content editors will see a counter when you limit a text field to be min="30" max="70" characters.
Would be a very nice GUI update.
Because it would make WebForms possible in the normal(!) Tridion GUI.
Creating new fields will then be possible by content management.
Creating new HTML5 webforms (tested!) takes then less then 2 minutes.
So please update the GUI to full xsd support.
We are creating xml files that we want to be compliant with the following xsd: http://www.topografix.com/gpx/1/1/gpx.xsd This xsd supports '...extending by adding your own elements here ...', see the extensionsType, which I have copied below for convenience.
1) I don't understand whether annotation and documentation are literal element names that would appear in compliant xml. I believe they are not but need confirmation. I'm assuming then that a compliant document would simply have any number of our own custom elements anywhere inside of any [extensions] element, correct?
2) Why are there two pairs of annotation/documentation elements below, with one in a sequence?
<xsd:complexType name="extensionsType">
<xsd:annotation>
<xsd:documentation>
You can add extend GPX by adding your own elements from another schema here.
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded">
<xsd:annotation>
<xsd:documentation>
You can add extend GPX by adding your own elements from another schema here.
</xsd:documentation>
</xsd:annotation>
</xsd:any>
</xsd:sequence>
</xsd:complexType>
1) From the XML Schema specification: "Annotations provide for human- and machine-targeted annotations of schema components." Schema authors use xsd:documentation as, say Java or .NET, developers use comments.
Annotations are XML Schema artifacts; they are not to show up in an XML document. And yes, your extensions elements should go under <extensions/>; you may use any namespace, other than http://www.topografix.com/GPX/1/1
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!-- Sample XML generated by QTAssistant (http://www.paschidev.com) -->
<gpx xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.1" creator="creator1" xmlns="http://www.topografix.com/GPX/1/1">
<extensions>
<my:element xmlns:my="urn:tempuri-org:some">Hello!</my:element>
</extensions>
</gpx>
2) Hard to say why there are two with the same comment; the difference though is that one documents the complex type, while the other the xsd:any element. I would personally have used different comments, first to explain what the complex type is for, the second just as shown.