I use Apache XmlSchema 2.2.1 to parse XSD schema. I has the following schema:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="http://www.example.com/aigu"
xmlns="http://www.example.com/aigu"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb" jxb:version="2.0">
<xs:attribute name="label" type="xs:string" />
<xs:element name="object">
<xs:complexType>
<xs:attribute ref="label" form="unqualified"/>
</xs:complexType>
</xs:element>
</xs:schema>
The following code produces exception
import org.apache.ws.commons.schema.XmlSchemaCollection;
import org.xml.sax.InputSource;
import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;
public class Aigu {
public static void main(String[] args) {
String schema = "HERE_IS_CONTENT_OF_SCHEMA";
XmlSchemaCollection collection = new XmlSchemaCollection();
collection.read(new InputSource(new ByteArrayInputStream(schema.getBytes(StandardCharsets.UTF_8))));
}
}
Stacktrace:
Exception in thread "main" java.lang.IllegalArgumentException: local part cannot be "null" when creating a QName
at javax.xml.namespace.QName.<init>(QName.java:244)
at javax.xml.namespace.QName.<init>(QName.java:188)
at org.apache.ws.commons.schema.utils.XmlSchemaNamedWithFormImpl.setName(XmlSchemaNamedWithFormImpl.java:117)
at org.apache.ws.commons.schema.utils.XmlSchemaNamedWithFormImpl.setForm(XmlSchemaNamedWithFormImpl.java:105)
at org.apache.ws.commons.schema.XmlSchemaAttribute.setForm(XmlSchemaAttribute.java:170)
at org.apache.ws.commons.schema.SchemaBuilder.handleAttribute(SchemaBuilder.java:959)
at org.apache.ws.commons.schema.SchemaBuilder.handleAttribute(SchemaBuilder.java:923)
at org.apache.ws.commons.schema.SchemaBuilder.handleComplexType(SchemaBuilder.java:307)
at org.apache.ws.commons.schema.SchemaBuilder.handleElement(SchemaBuilder.java:420)
at org.apache.ws.commons.schema.SchemaBuilder.handleSchemaElementChild(SchemaBuilder.java:1512)
at org.apache.ws.commons.schema.SchemaBuilder.handleXmlSchemaElement(SchemaBuilder.java:659)
at org.apache.ws.commons.schema.SchemaBuilder.build(SchemaBuilder.java:157)
at org.apache.ws.commons.schema.XmlSchemaCollection.read(XmlSchemaCollection.java:508)
at org.apache.ws.commons.schema.XmlSchemaCollection.read(XmlSchemaCollection.java:717)
at org.apache.ws.commons.schema.XmlSchemaCollection.read(XmlSchemaCollection.java:565)
at com.netcracker.mediation.transition.model.xmltojava.Aigu.main(Aigu.java:23)
Is it a bug in Apache code or my schema is invalid?
The attribute form cannot be used in an attribute use that has a ref (as constrained in point 3.2 in this paragraph of the XML Schema specification).
Also, since the target of the reference is a top-level attribute declaration in a schema with a target namespace, its form, if it were allowed to put it explicitly, would have to be qualified.
It may explain the error, as the trace seems to indicate that it happens there.
This would be the corrected schema:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="http://www.example.com/aigu"
xmlns="http://www.example.com/aigu"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb" jxb:version="2.0">
<xs:attribute name="label" type="xs:string" />
<xs:element name="object">
<xs:complexType>
<xs:attribute ref="label"/>
</xs:complexType>
</xs:element>
</xs:schema>
Related
I am writing an XSD file to automatically generate Java classes to parse an XML file like this:
<pipeline:Pipeline
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:pipeline="http://www.intershop.de/pipeline/2010"
name="ViewCheckoutReview" type="view"
>
<nodes xsi:type="pipeline:Text" nodeID="Text0"/>
</pipeline:Pipeline>
I'm having issues when unmarshalling the xsi:type attribute on the <nodes> element.
These are my XSD files:
schema0.xsd:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:pipeline="http://www.intershop.de/pipeline/2010"
attributeFormDefault="unqualified"
elementFormDefault="qualified"
targetNamespace="http://www.intershop.de/pipeline/2010"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
<xs:import schemaLocation="schema1.xsd" />
<xs:element name="Pipeline">
<xs:complexType>
<xs:sequence>
<xs:element ref="nodes" />
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required" />
<xs:attribute name="type" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
</xs:schema>
schema1.xsd:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema
attributeFormDefault="unqualified"
elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>
<xs:element name="nodes">
<xs:complexType>
<xs:attribute name="nodeID" type="xs:string" use="required" />
<xs:attribute ref="xsi:type" use="required" />
</xs:complexType>
</xs:element>
</xs:schema>
When I execute xjc using these XSD I get this error:
[ant:jaxb] parsing a schema...
[ant:jaxb] [ERROR] src-resolve.4.2: Error resolving component 'xsi:type'. It was detected that 'xsi:type' is in namespace 'http://www.w3.org/2001/XMLSchema-instance', but components from this namespace are not referenceable from schema document 'file:/C:/Projects/test/xsd/schema1.xsd'. If this is the incorrect namespace, perhaps the prefix of 'xsi:type' needs to be changed. If this is the correct namespace, then an appropriate 'import' tag should be added to 'file:/C:/Projects/test/xsd/schema1.xsd'.
[ant:jaxb] line 12 of file:/C:/Projects/test/xsd/schema1.xsd
[ant:jaxb]
[ant:jaxb] [ERROR] src-resolve: Cannot resolve the name 'xsi:type' to a(n) 'attribute declaration' component.
[ant:jaxb] line 12 of file:/C:/Projects/test/xsd/schema1.xsd
[ant:jaxb]
[ant:jaxb] Failed to parse a schema.
I have found a possible solution here on StackOverflow, which consists in adding the namespace attribute in the #XmlAttribute annotation of the generated Java class' field:
#XmlAttribute(name = "type", required = true, namespace = "http://www.w3.org/2001/XMLSchema-instance")
protected String type;
and changing schema1.xsd like this:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema
attributeFormDefault="unqualified"
elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>
<xs:element name="nodes">
<xs:complexType>
<xs:attribute name="nodeID" type="xs:string" use="required" />
<!-- 'type' attribute is not referenced anymore -->
<xs:attribute name="type" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
</xs:schema>
This solution works but I don't like it, because I would need to change manually, every time I run xjc, the generated Java classes to add that namespace attribute.
What I would like instead is to put something in the XSD file (or in a XJB file maybe?) which adds that namespace attribute automatically when I run xjc.
If I don't add that namespace attribute on the #XmlAttribute annotation, value of type attribute is always null:
public static void main(String[] args) throws JAXBException
{
File xmlFile = new File("D:\\temp\\test.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(Pipeline.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
Pipeline pipeline = (Pipeline) unmarshaller.unmarshal(xmlFile);
Nodes node = pipeline.getNodes();
System.out.println(node.getType()); // prints null
}
Currently i have to hard-code the schema version (or parse it) manually in java code when working with generated JAXB classes. This can easily lead to mistakes when changing the XML schema version and feels wrong.
What i want is to specify the schema version in the schema and let xjc generate a constant in the corresponding root element class.
I haven't found a JAXB plugin or binding mechanism which i can use to meet these requirements.
example.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:my="my:namespace:v1"
targetNamespace="my:namespace:v1"
xmlns="my:namespace:v1"
elementFormDefault="qualified"
attributeFormDefault="unqualified"
<!-- Use this version information in generated class! -->
version="1.0">
<xs:element name="root" type="RootType"/>
<xs:complexType name="RootType">
<xs:sequence>
<xs:element name="name" type="xs:string" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
<xs:attribute name="xsdVersion" type="xs:string" use="required"/>
[...]
</xs:schema>
Generated RootType.class:
[...]
public class RootType {
protected String name;
protected String xsdVersion;
// This shall be generated too
public static final GENERATED_WITH_VERSION = "1.0";
[...]
}
My webservice should be able to validate xml-input against a schema(request.xsd). The complextyped only element in the schema owns different subelements of types which are defined in other xsds. I am importing all thess xsds. At the end however element type cannot be resolved.
this ist my "request.xsd":
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:fe="http://www.some.dir/featurenamespace"
xmlns="http://this.is.my.space"
targetNamespace="http://this.is.my.space"
elementFormDefault="qualified">
<xs:import schemaLocation=" http://www.some.dir/featurenamespace/cmplxtypes.xsd "
namespace=" http://www.some.dir/featurenamespace"/>
<xs:element name="elem1" type="request"/>
<xs:complexType name="request">
<xs:complexContent>
<xs:extension base="fe:complexElement">
<xs:sequence>
<xs:element name="record" type="fe:complexElement "/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:schema>
This is the schema (e.g. cmplxtypes.xsd) where the type 'complexElement' is defined:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:fe="http://www.some.dir/featurenamespace"
xmlns:ofe ="http://www.some.dir/otherfeaturenamespace"
targetNamespace="http://www.some.dir/featurenamespace"
version="1.1.0"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:include schemaLocation="fe_types.xsd" />
<xs:import schemaLocation="ofe_types.xsd" namespace="http://www.some.dir/otherfeaturenamespace"/>
<xs:complexType name="complexElement">
<xs:sequence>
<xs:element name="feature" type="fe:FeatureType "/>
<xs:element name="otherfeature" type="ofe:otherFeatureType"/>
</sequence>
</xs:complexType>
The files: cmplxtypes.xsd, fe_types.xsd and ofe_types.xsd share the same namespace.
Now, trying to validate myxml against request.xsd I get: cannot resolve 'complexElement' to a 'type defintion' component.
I do appreciate any help.
There are several inconsistencies in the schemas that may explain the error.
request.xsd doesn't appear to be importing cmplxtypes.xsd, where fe:complexElement is defined.
<xs:import
schemaLocation="http://www.some.dir/featurenamespace/cmplxtypes.xsd"
namespace=" http://www.some.dir/featurenamespace" />
cmplxtypes.xsd includes ofe_types.xsd even though the namespace does not match according to the import in request.xsd. Namespaces much match when including other schemas (or the included schema must have no target namespace).
I have a JAXB class, which has an element coming from another namespace. I would like to have an ANY element as well, which collects all the elements not described in the JAXB class. So I added a List<Object> annotated with the #XmlAnyElement.
I have generated an XSD from the JAXB class, but when I am validating I am getting an error: "cos-nonambig: "nb":b and WC[##other:""] (or elements from their substitution group) violate "Unique Particle Attribution". During validation against this schema, ambiguity would be created for those two particles."
The JAXB class
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType
public class Foo {
#XmlElement
String a;
#XmlElement(namespace="nb")
Bar b;
#XmlAnyElement
List<Object> other;
}
The XSD generated by JAXB
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0" xmlns:ns1="nb" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:import namespace="nb" schemaLocation="schema1.xsd"/>
<xs:complexType name="foo">
<xs:sequence>
<xs:element name="a" type="xs:string" minOccurs="0"/>
<xs:element ref="ns1:b" minOccurs="0"/>
<xs:any processContents="skip" namespace="##other" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="bar">
<xs:sequence>
<xs:element name="bid" type="xs:string" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0" targetNamespace="nb" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:import schemaLocation="schema2.xsd"/>
<xs:element name="b" type="bar"/>
</xs:schema>
How should I add the XmlAnyElement to pass the validation?
I want to view the below defined xml schema into my expected xml. Can anyone help me what to write in XSD. Thanks in advance.
XML SCHEMA:
<xs:element name="Animal">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="type" type="xs:string" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
EXPECTED OUTPUT in XML: <Animal type="carnivore">Tiger</Animal>.
With a schema containing only the element you showed, you can generate the instance you want in Java using JAXB. I added some context to your example, and included a namespace. This is the full XML Schema file (I called it animals.xsd):
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="http://animals"
targetNamespace="http://animals"
elementFormDefault="qualified">
<xs:element name="Animal">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="type" type="xs:string" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:schema>
Using the xjc tool (XSD to Java Compiler) you can generate classes from XML Schemas. So you can simply run:
xjc animals.xsd
And it will generate these files
animals/Animal.java
animals/ObjectFactory.java
animals/package-info.java
Place these in your classpath. Now you can write a simple program where you can create instances using that class, and then serialize it to XML using a JAXB marshaller:
import animals.Animal;
import javax.xml.bind.*;
public class App {
public static void main(String[] args) throws JAXBException {
Animal tiger = new Animal();
tiger.setType("carnivore");
tiger.setValue("Tiger");
JAXBContext jaxbContext = JAXBContext.newInstance(Animal.class);
Marshaller m = jaxbContext.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
m.marshal(tiger, System.out);
}
}
The result will be printed to the console:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Animal xmlns="http://animals" type="carnivore">Tiger</Animal>