I have a number of required soap headers defined in XSDs that I am not allowed to change, as existing clients are already using these in production.
In one of these schemas there are a number of imports with the same namespace value. When I attempt loading this schema into my validation interceptor I get an exception saying that the sdsd:SystemName (2nd element in the sequence) is undefined.
If I open the XSD in IntelliJ Idea 13 I get red markings for sdsd:SystemName and the rest of the list of elements. Only the sdsd:SystemOwnerName is found and loaded.
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:sdsd="http://www.sdsd.dk/dgws/2010/08" xmlns:sdsd201206="http://www.sdsd.dk/dgws/2012/06" targetNamespace="http://www.sdsd.dk/dgws/2012/06" elementFormDefault="qualified" attributeFormDefault="unqualified">
<import namespace="http://www.sdsd.dk/dgws/2010/08" schemaLocation="../../2010/08/SystemOwnerName.xsd" />
<import namespace="http://www.sdsd.dk/dgws/2010/08" schemaLocation="../../2010/08/SystemName.xsd" />
<import namespace="http://www.sdsd.dk/dgws/2010/08" schemaLocation="../../2010/08/SystemVersion.xsd" />
<import namespace="http://www.sdsd.dk/dgws/2010/08" schemaLocation="../../2010/08/OrgResponsibleName.xsd" />
<import namespace="http://www.sdsd.dk/dgws/2010/08" schemaLocation="../../2010/08/OrgUsingName.xsd" />
<import namespace="http://www.sdsd.dk/dgws/2010/08" schemaLocation="../../2010/08/OrgUsingID.xsd" />
<import namespace="http://www.sdsd.dk/dgws/2010/08" schemaLocation="../../2010/08/RequestedRole.xsd" />
<element name="WhitelistingHeader" type="sdsd201206:WhitelistingHeader">
<annotation>
<documentation xml:lang="en-GB">SDSD Whitelisting header.</documentation>
<documentation xml:lang="da-DK">SDSD Whitelisting header.</documentation>
</annotation>
</element>
<complexType name="WhitelistingHeader">
<sequence>
<element ref="sdsd:SystemOwnerName" minOccurs="1" maxOccurs="1" />
<element ref="sdsd:SystemName" minOccurs="1" maxOccurs="1" />
<element ref="sdsd:SystemVersion" minOccurs="1" maxOccurs="1" />
<element ref="sdsd:OrgResponsibleName" minOccurs="1" maxOccurs="1" />
<element ref="sdsd:OrgUsingName" minOccurs="1" maxOccurs="1" />
<element ref="sdsd:OrgUsingID" minOccurs="1" maxOccurs="1" />
<element ref="sdsd:RequestedRole" minOccurs="1" maxOccurs="1" />
</sequence>
</complexType>
`
I have read this thread One xml namespace equals one and only one schema file? and can confirm that if I make a new 'master' schema that includes the schemas that are imported in the schema shown above and then change the imports in the schema shown above to a single include of the 'master' schema my Spring-ws validation interceptor is working correctly.
However since changing the schema is not an option I am looking for other options.
I have found Xerces documentation and Validate XML with loading schemas at runtime, failure depending on schema order suggesting that I can set the feature "http://apache.org/xml/features/validation/schema/handle-multiple-imports" to true on the XmlSchemaFactory in order to make Xerces not fail when validating a schema with multiple imports to the same namespace. However I have my own SoapHeaderValidatingInterceptor that extends the AbstractValidatingInterceptor, which in turn uses the Spring WS internal XmlValidatorFactory to create the XmlValidator that is used to validate the XSDs.
Any tips as to how I can enable the handle-multiple-imports feature will be greatly appreciated.
Related
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>
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
I have a use case to define XSD schema to describe a structure that is similar to Files and Directories.
File is a complex type with multiple attributes.
Directory is a File, so it should be an extension of a File or in other words, inherited from a File.
Directory can contain more Files and sub Directories, so it should be defined recursively.
File could be an element.
Directory could be an root element.
Can anyone provide an example schema file?
For example, the following C++ code compiles/runs fine:
#include <iostream>
#include <vector>
using namespace std;
class FileClass {
public:
string name;
int type;
string path;
long long size;
virtual int open(){
};
virtual int close (){
};
virtual ~FileClass(){
};
};
class DirectoryClass: public FileClass {
public:
vector<FileClass*> dir_contents;
};
int main() {
cout<<"started"<<endl;
DirectoryClass root;
root.open();
FileClass* newFile = new FileClass();
root.dir_contents.push_back(newFile);
DirectoryClass* subDir = new DirectoryClass();
root.dir_contents.push_back(subDir);
root.close();
cout<<"finished"<<endl;
}
As you can see, the DirectoryClass contains only one vector of FileClass, and it's capable of storing sub dirs since DirectoryClass is derived from FileClass.
I'd agree with Tony, why derive Directory from File?
But if thats what your trying to model...
<?xml version="1.0" encoding="utf-8" ?>
<!--Created with Liquid XML Studio 2013 Designer Edition 11.0.0.0 (http://www.liquid-technologies.com)-->
<xs:schema elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="FileType">
<xs:attribute name="name"
type="xs:string"
use="required" />
<xs:attribute name="creationDate"
type="xs:dateTime"
use="required" />
</xs:complexType>
<xs:element name="File"
type="FileType" />
<xs:element name="Directory">
<xs:complexType>
<xs:complexContent>
<xs:extension base="FileType">
<xs:sequence>
<xs:element ref="File"
minOccurs="0"
maxOccurs="unbounded" />
<xs:element ref="Directory"
minOccurs="0"
maxOccurs="unbounded" />
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
</xs:schema>
Then if you are then trying to read/write the structured XML data from C#, C++, Java etc you could look at XML Data Binding. This generates a set of strongly typed objects from your XSD.
That changes things a bit and compilcates the XML. There are 2 approaches ComplexType Inheritance or Substitution Groups. Complex Types are a better fit to the breif.
<?xml version="1.0" encoding="utf-8" ?>
<!--Created with Liquid XML Studio 2013 Designer Edition (Trial) 11.0.0.0 (http://www.liquid-technologies.com)-->
<xs:schema elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="FileType">
<xs:attribute name="name"
type="xs:string"
use="required" />
<xs:attribute name="creationDate"
type="xs:dateTime"
use="required" />
<xs:attribute name="type"
type="xs:int" />
<xs:attribute name="size"
type="xs:long" />
</xs:complexType>
<xs:complexType name="DirectoryType">
<xs:complexContent>
<xs:extension base="FileType">
<xs:sequence>
<xs:element name="Content"
type="FileType"
minOccurs="0"
maxOccurs="unbounded" />
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="Directory"
type="DirectoryType" />
</xs:schema>
Sample XML
<?xml version="1.0" encoding="utf-8"?>
<!-- Created with Liquid XML Studio 2013 Designer Edition (Trial) 11.0.0.0 (http://www.liquid-technologies.com) -->
<Directory xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="FoldersCT.xsd"
name="string"
creationDate="1975-12-12T08:25:00.94"
type="393"
size="-5191">
<Content name="FileA1"
creationDate="1993-02-23T21:13:52.11"
type="4931"
size="-1984" />
<Content name="FileA2"
creationDate="1991-12-26T15:57:44.30"
type="-6155"
size="18" />
<Content name="FileA3"
creationDate="1979-01-05T21:36:13.80"
type="8362"
size="5579" />
<Content xsi:type="DirectoryType"
name="DirA4"
creationDate="1979-01-05T21:36:13.80"
type="8362"
size="5579">
<Content name="FileB1"
creationDate="1979-01-05T21:36:13.80"
type="8362"
size="5579" />
<Content name="FileB2"
creationDate="1979-01-05T21:36:13.80"
type="8362"
size="5579" />
</Content>
</Directory>
Note the use of the xsi:type="DirectoryType" attribute in the directories. This tells the XML Parser that the content is defined by DirectoryType. Without this its a file. This is what your spec says, but its pretty messy I would say.
Another solution is to use substitution groups, which personally I don't like as they are difficult to read in a schema. This effectivley this is the same as the orginal solution.
<?xml version="1.0" encoding="utf-8" ?>
<!--Created with Liquid XML Studio 2013 Designer Edition (Trial) 11.0.0.0 (http://www.liquid-technologies.com)-->
<xs:schema elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="FileType">
<xs:attribute name="name"
type="xs:string"
use="required" />
<xs:attribute name="creationDate"
type="xs:dateTime"
use="required" />
<xs:attribute name="type"
type="xs:int" />
<xs:attribute name="size"
type="xs:long" />
</xs:complexType>
<xs:element name="File"
type="FileType"
substitutionGroup="File" />
<xs:element name="Directory"
substitutionGroup="File">
<xs:complexType>
<xs:complexContent>
<xs:extension base="FileType">
<xs:sequence>
<xs:element ref="File"
minOccurs="0"
maxOccurs="unbounded" />
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
</xs:schema>
Sample XML
<?xml version="1.0" encoding="utf-8"?>
<!-- Created with Liquid XML Studio 2013 Designer Edition (Trial) 11.0.0.0 (http://www.liquid-technologies.com) -->
<Directory xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="FoldersSG.xsd"
name="string"
creationDate="1992-01-13T17:58:08.38"
type="-2296"
size="-8752">
<File name="string"
creationDate="1982-11-03T17:57:40.96"
type="6813"
size="5278" />
<File name="string"
creationDate="1986-12-08T12:38:03.46"
type="4479"
size="8453" />
<Directory name="string"
creationDate="1992-01-13T17:58:08.38"
type="-2296"
size="8752">
<File name="string"
creationDate="1982-11-03T17:57:40.96"
type="6813"
size="5278" />
<File name="string"
creationDate="1986-12-08T12:38:03.46"
type="4479"
size="8453" />
</Directory>
</Directory>
This is (part of) the XML that I want to define in my schema. I have already added a unique constraint for the name attribute of the <add /> element.
<parameters>
<add name="one" value="1" />
<add name="two" value="2" />
</parameters>
But I don't know how to prevent <add name="" value="" />. I have tried the following schema, but it's not honored:
<xs:attribute name="name" use="required" type="config:NonEmptyString" />
<xs:simpleType name="NonEmptyString">
<xs:restriction base="xs:string">
<xs:minLength value="1" />
</xs:restriction>
</xs:simpleType>
config is the target namespace for the schema.
Edit: I'm using Visual Studio to validate XML as I write it in the XML editor.
I did a quick test; created an XSD out of the XML and added your constraint:
<?xml version="1.0" encoding="utf-8"?>
<!--XML Schema generated by QTAssistant/XML Schema Refactoring (XSR) Module (http://www.paschidev.com)-->
<xsd:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="parameters">
<xsd:complexType>
<xsd:sequence>
<xsd:element maxOccurs="unbounded" name="add">
<xsd:complexType>
<xsd:attribute name="name" type="NonEmptyString" use="required"/>
<xsd:attribute name="value" type="xsd:unsignedByte" use="required"/>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:simpleType name="NonEmptyString">
<xsd:restriction base="xsd:string">
<xsd:minLength value="1"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
I've validated this XML:
<parameters>
<add name="" value="1" />
<add name="two" value="2" />
</parameters>
And I've got this error:
Error occurred while loading [], line 2 position 8
The 'name' attribute is invalid - The value '' is invalid according to its datatype 'NonEmptyString' - The actual length is less than the MinLength value.
I would say that the problem is rather with your XSD processor, as opposed to the XSD itself. Maybe you could update the post with the processor you're using?
Visual Studio 2010 does the validation correctly - it produces the warning:
Warning 4 The 'name' attribute is invalid - The value '' is invalid according to its datatype 'config:NonEmptyString' - The actual length is less than the MinLength value. XMLFile1.xml 3 14 Miscellaneous Files
but for some reason (bug?) it does not underline the error position in the XML editor.
I am using BizTalk 2006 R2 to generate a web reference from a WSDL file.
Comparing the generated XSD to the WSDL, it is apparent that a lot of information has been lost.
Consider the following extract from the WSDL:
<s:element form="unqualified" minOccurs="0" maxOccurs="4" name="Applicant">
<s:complexType>
<s:sequence>
<s:element form="unqualified" minOccurs="1" maxOccurs="1" name="ApplicantIdentifier">
<s:simpleType>
<s:restriction base="s:string" />
</s:simpleType>
</s:element>
<s:element form="unqualified" minOccurs="0" maxOccurs="1" name="Name">
<s:complexType>
<s:sequence>
<s:element form="unqualified" minOccurs="0" maxOccurs="1" name="Title">
<s:simpleType>
<s:restriction base="s:string">
<s:maxLength value="10" />
</s:restriction>
</s:simpleType>
</s:element>
<s:element form="unqualified" minOccurs="0" maxOccurs="1" name="Forename">
<s:simpleType>
<s:restriction base="s:string">
<s:pattern value="[0-9A-Za-z \-]*" />
<s:maxLength value="15" />
<s:minLength value="1" />
</s:restriction>
</s:simpleType>
</s:element>
<!-- more -->
</s:sequence>
</s:complexType>
</s:element>
</s:sequence>
</s:complexType>
</s:element>
The equivalent XSD which BizTalk has generated is:
<xs:element minOccurs="0" maxOccurs="unbounded" form="unqualified" name="Applicant">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" form="unqualified" name="ApplicantIdentifier" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="1" form="unqualified" name="Name">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" form="unqualified" name="Title" type="xs:string" />
<xs:element minOccurs="0" maxOccurs="1" form="unqualified" name="Forename" type="xs:string" />
<!-- more -->
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
So, the XSD has lost the restriction patterns and has set its own values for minOccurs and maxOccurs.
I need to map from another source to the XSD and I wish to trap data that does not conform to the WSDL at that stage.
Does anyone know why BizTalk has not preserved the restrictions in the XSD; or how I can generate non-lossy XSD?
Unless you're doing schema validation in a BizTalk pipeline, restrictions and maxoccurs > 1 aren't actually going to do anything - they're not used by BizTalk at runtime. I'm guessing this is the reason why the web reference is lossy.
I've personally never liked the 'add web reference' feature, or even the 'add adapter metadata'/WCF. If your wsdl is changing that frequently that manually copying the type definitions into an xsd file is too much work:
a) look at building a simple console app to retrieve the wsdl, extract the type(s) and update the xsd file (kick it off from the External Tools menu in VS), and
b) work out what's going wrong with your development process that requires service contract changes that often!
Have you tried using the WCF adapter rather than the "add web reference" to get this done?
Here is an example...
http://blogs.digitaldeposit.net/SARAVANA/post/2007/05/31/BizTalk-2006-R2-consume-an-ASMX-webservice-using-WCF-BasicHttp-adapter.aspx