How could I combine two XSDs to one? I want to use xjc to generate Java classes from the final XSD.
The two XSDs I have:
http://www.topografix.com/GPX/1/0/gpx.xsd
http://www.groundspeak.com/cache/1/0/1/cache.xsd
An exisiting XML document using a combination of both:
http://www.cachewiki.de/wiki/GPX#Geocaching.com
Import one schmema in definition of another:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:gpx="http://www.topografix.com/GPX/1/0"
xmlns:groundspeak="http://www.groundspeak.com/cache/1/0/1/cache.xsd"
targetNamespace="http://www.topografix.com/GPX/1/0" elementFormDefault="qualified">
<xsd:import schemaLocation="cache.xsd"
namespace="http://www.groundspeak.com/cache/1/0/1/cache.xsd" />
...
Import your one xsd schema in to other.
Related
I implemented an xsd scanner, which creates an targetNamespace=<file.xsd> catalog.
Includes are filtered, so the catalog has only the root files of the targetNamespace.
With this catalog I'm resolving the required files (using a LSResourceResolver) to validate incoming xml files.
Map
namespace1=path/xsdForNameSpace1
namespace2=path/xsdForNameSpace2
:
But now I got multiple XSD, containing different content, but implementing the same targetNamespace.
Imho this is not correct, one namespace one root xsd - done
Example
schema1.xsd:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.xxxxxxx.com/texxxxxxx"
targetNamespace="http://www.xxxxxxx.com/texxxxxxx"
elementFormDefault="qualified">
<xsd:include schemaLocation="xxxxxx_xxxxxx_xxxxx_xxxxx.xsd"/>
<xsd:element name="ab120">
<xsd:complexType>
:
schema2.xsd:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.xxxxxxx.com/texxxxxxx"
targetNamespace="http://www.xxxxxxx.com/texxxxxxx"
elementFormDefault="qualified">
<xsd:include schemaLocation="xxxxxx_xxxxxx_xxxxx_xxxxx.xsd"/>
<xsd:element name="ab122">
<xsd:complexType>
:
I have two xml files are implementing the identical namespace http://www.xxxxxxx.com/texxxxxxx one with a root element ab120 the other with a root element ab122.
In this case my map contains only one of the implementing xsd files and I've no idea how to resolve the correct xsd for the incoming xml.
The incoming xml files look like this.
file1.xml:
<ab120 xmlns="http://www.xxxxxxx.com/texxxxxxx" ...>
:
</ab120>
file2.xml
<ab122 xmlns="http://www.xxxxxxx.com/texxxxxxx" ...>
:
</ab122>
The LSResourceResolver interface does not give me access to the xml, so I can't decide according the root node, which xsd I should use.
My temporary solution:
I added a second index with (namespace,xsd_file_name) that resolves correctly when the xml provides the implementing file (systemID)
targenNamespace="namespace myfile.xsd"
My question is, is it correct to specifiy multiple XSD file implementing the same namespace with different xsd structures ?
Edit:
It seemed to be not clear enough. Added two examples
My question is, is it correct to specifiy multiple XSD file implementing the same namespace with different xsd structures ?
Yes, that is a valid use of XML schema. A schema does not have to be represented by a single XSD file. Please see https://www.w3.org/TR/xmlschema-0/#SchemaInMultDocs and https://www.w3.org/TR/xmlschema-0/#import
You may also find this thread helpful: What's the difference between xsd:include and xsd:import?
Ok after asking w3c there is nothing in the specs that precludes this.
Reusing a targetNamespace with different content is allowed.
However, how to handle this, if you have to validate XMLs, is on your own and depends on the situation.
Possible solutions could be adding a version tag to the xml header or combine schemas if possible.
In my context nothing of the above would help, the resolver interface does not allow additional information, and the xsds can not be combined by a choice.
The only way to solve the issue is creating different index, resolver combinations. When creating the validator I have to use the correct resolver according to the origin where the xml came from.
How about including the two existing XSDs in a third one and use this for validation?
schema3.xsd:
<?xml version="1.0" encoding="utf-8" ?>
<xs:schema targetNamespace="http://www.xxxxxxx.com/texxxxxxx"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xs:include schemaLocation="schema1.xsd"/>
<xs:include schemaLocation="schema2.xsd"/>
</xs:schema>
I'm very new to JAXB, so I'm having trouble cracking this (I assume) very simple use case.
I have a set of schemas I got. I have no control over those, I cannot change them. In these schemas, I have declarations such as
<xs:complexType name="CustomerType">
...
I try to generate classes from these. So such a declaration becomes
#XmlType(name = "CustomerType", propOrder = {
"field1",
"field2"
})
public class CustomerType {
...
Then I need to use this class to create XML messages using a RestTemplate. The problem is, the object in the XML message is not supposed to be "CustomerType", it's supposed to be just "Customer". Like I said, I cannot edit the schemas. I also cannot directly edit the generated sources. I need some kind of external customization that tells either the source generating process, or the marshalling process, how to transform the names of the objects. Any advice will be greatly appreciated.
You can use bindings to customize class or property names. Typically you'll have a file like bindings.xjb like this:
<jaxb:bindings version="1.0" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
jaxb:extensionBindingPrefixes="xjc">
<jaxb:bindings schemaLocation="schema.xsd" node="/xsd:schema">
<jaxb:bindings node="xsd:customType[#name='CustomerType']">
<jaxb:class name="Customer"/>
</jaxb:bindings>
<jaxb:bindings node="xsd:customType[#name='CustomerType']//xsd:element[#name='field1']">
<jaxb:property name="f1"/>
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
There are quite a few things you can customize with bindings (see this), but certainly not everything.
The way DTO objects are created is:
You define all the types at one place like: CustomerType, UserType, OrderType and so on.
You then create another schema and import appropriates XSD's within where you have defined multiple types. Then you actually use/aggregate these type definitions to create your XML Schema for objects . Something like below
<xs:complexType name="CustomerOrders">
<xs:element name="Customer" type="CustomerType">
<xs:attribute name="Orders" type="OrderType">
this is my first question, so please be gentle ;)
I'm stuck with a weird problem. Essentially i get three XSD definitions like the following:
PartA.xsd
targetNameSpace="PartA"
include="PartB.xsd"
PartB.xsd
<!-- no namespace definition!!! -->
PartC.xsd
targetNameSpace="PartC"
inlude="PartB.xsd"
import="PartA.xsd"
The error pops up, when binding PartC via JAXB to Java classes:
A class/interface with the same name "b.exampleType" is already in use. Use a class customization to resolve this conflict.
This confusing error happened most likely because the schema uses a technique called "chameleon schema", which causes a single definition to be loaded multiple times into different namespaces. See http://forums.java.net/jive/thread.jspa?threadID=18631 for more about this.
Following the link, i found out, the actual error lies in PartB, which has no namespace declaration! This method is called Chameleon Schema. The defined types in PartB will adopt the namesspace of the importing XSD.
So in my case, there are two namespaces for the same type:
"PartA"
"PartC"
And this is, where JAXB breaks down. I haven't found a way to bind PartC properly. And (to make things tricky) i have chance to change the original XSD definitions!
Has anyone come across this phenomena or something like that before and has a valid workaround for it?
I was facing the same problem using wsdl2java:
WSDLToJava Error: Thrown by JAXB : A class/interface with the same
name "Respuesta" is already in use. Use a class customization to
resolve this conflict.
But this question pointed me in the right direction.
Using wsdl2java from CFX you can customize how elements are binded to classes using a binding.xml file.
For example:
/Applications/apache-cxf-2.7.13/bin/wsdl2java -b ./src/main/resources/binding.xml -V -d src/main/java -compile -classdir target/classes http://someurl.wsdl
The key is to explain in the binding.xml to name certain xsd element with one especific className to avoid colissions:
<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="./someXsdFile.xsd">
<!-- Rename the respuesta class to resolve a naming conflict with other Respuesta element already defined-->
<jxb:bindings node="//xs:element[#name='respuesta']/xs:complexType">
<jxb:class name="Respuesta2" />
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>
Hope this helps to the next person with this problem using wsdl2java. I supose that other tools should allow similar aproaches to this problem.
I was having the same issue and the google search landed me here.
Your question is detailed enough and I was able to find the answer,
what I did is put the namespace in PartB.xsd and use XJC to generate the java classes.
I added the following:
xmlns:ns="http://www.myCompany.com/2009/01/CustSchema" targetNamespace="http://www.myCompany.com/2009/01/CustSchema"
The following is available, although it does not provide a lot of detail:
https://javaee.github.io/jaxb-v2/doc/user-guide/ch03.html#compiling-xml-schema-how-modularization-of-schema-interacts-with-xjc
There is one workaround for this problem. More specifically what you have to do is:
1.Define proxy schema (PartB_proxy.xsd) for PartB.xsd (with no namespace definition) and specify temporary namespace (for example PartB):
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" xmlns="PartB"
targetNamespace="PartB">
<xsd:include schemaLocation="partB.xsd"/>
2.Prepare bindings file (for large schemas this step could be automatized by generating episode file - more details in my article - I've attached link at the end of this post) - this step is required to avoid generating duplicate classes for PartB schema (by default the duplicate classes that come from PartB schema will be generated for PartA and PartC schemas/java packages):
<bindings version="2.1" xmlns="http://java.sun.com/xml/ns/jaxb"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<bindings scd="x-schema::partA" xmlns:partA="PartA">
<bindings scd="~partA:SomeType1">
<class ref="SomeType1"/>
</bindings>
<bindings scd="~partA:SomeType2">
<class ref="SomeType2"/>
</bindings>
</bindings>
<bindings scd="x-schema::partC" xmlns:partC="PartC">
<bindings scd="~partC:SomeType1">
<class ref="SomeType1"/>
</bindings>
<bindings scd="~partC:SomeType2">
<class ref="SomeType2"/>
</bindings>
</bindings>
</bindings>
3.Generate JAXB classes using XJC, example Gradle task (I am using Moxy implemetnation but You can use default XJC generator from JDK 8 or standalone JAXB library for newer JDK versions):
task generateExampleChameleonSourcesWithMoxy(type: JavaExec) {
classpath = configurations.moxy
main = 'org.eclipse.persistence.jaxb.xjc.MOXyXJC'
args '-b'
args 'src/main/resources/example/chameleon/bindings.xml'
args '-d'
args 'src/main/generated'
args 'src/main/resources/example/chameleon/PartA.xsd'
args 'src/main/resources/example/chameleon/PartB_proxy.xsd'
args 'src/main/resources/example/chameleon/PartC.xsd'
}
4.Remove proxy namespace (partB) from package-info.java generated for partB schema:
javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package partB;
5.Finally You can marshal and unmarshal these XML documents using the Default Namespace Remapping technique by:
defining the default namespace for the types with no namespace:
com.sun.xml.internal.bind.defaultNamespaceRemap property (JDK JAXB >=JDK 1.8)
com.sun.xml.bind.defaultNamespaceRemap property (External JAXB JDK 1.9+)
performing marshalling/unmarshalling as usual
Here’s the code that is responsible for that (JDK 1.8):
//Initialize JaxbContext
Map<String, String> properties = new HashMap<>();
properties.put("com.sun.xml.internal.bind.defaultNamespaceRemap", "partC");
JAXBContext jaxbContext = JAXBContext.newInstance(new Class[]{SomeType1.class}, properties);
//Unmarshall Message object file from example XML
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
Object messageObject = unmarshaller.unmarshal(getClass().getResourceAsStream("/example/chameleon/Division.xml"));
//Marshall message object back into XML
ByteArrayOutputStream xmlMessageOS = new ByteArrayOutputStream();
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.marshal(messageObject, xmlMessageOS);
System.out.println(xmlMessageOS.toString());
//Validate output XML with schema
InputStream xmlInputStream = new ByteArrayInputStream(xmlMessageOS.toByteArray());
Source xmlSource = new StreamSource(xmlInputStream);
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = schemaFactory.newSchema(getClass().getResource("/example/chameleon/PartC.xsd"));
Validator validator = schema.newValidator();
validator.validate(xmlSource);`
Unfortunately, You have to use different JAXB contexts for JAXB objects coming from PartA and PartC namespaces. This is required because JAXB default namespace remapping property is set per JAXB context - this way JAXB marshaller/unmarshaller knows how to deal with POJO objects that have no namespace defined (PartB).
Nevertheless, I do not think it is problematic as usually all the JAXB contexts are initialized once - during the application startup (in singleton).
To sum up, the workaround described above allows You to use JAXB to marshall/unmarshall XML documents without modifying the chameleon schemas. The proxy XSD file is used only at the beginning - for the process of generating JAXB objects (XJC). The marshalled/unmarshalled XML documents still conform to the original schemas. This technique is useful especially if You are not allowed to modify the schemas. I was dealing with that problem for read-only NDC standard (set of schemas) in 18.1 version defined by http://www.iata.org.
I've written an article on that topic: How to deal with Chameleon namespace design in JAXB. You will find it here: https://medium.com/#pziobron/how-to-deal-with-chameleon-namespace-design-in-jaxb-e36bcc03767d. Hopefully, You will find it useful.
So here's the scenario...I have an XSD file describing all the objects that I need. I can create the objects in Java using JAXB no problem. I have an XML/RDF file that I need to parse into those objects.
What is the EASIEST way to do this?
I have been looking into Jena and have played around with it, but can't see how to easily map the XML/RDF file to the XSD objects that were generated. Here is a snippet of the XSD file as well as the XML/RDF file:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:a="http://langdale.com.au/2005/Message#"
xmlns:sawsdl="http://www.w3.org/ns/sawsdl"
targetNamespace="http://iec.ch/TC57/2007/profile#"
elementFormDefault="qualified"
attributeFormDefault="unqualified"
xmlns="http://langdale.com.au/2005/Message#"
xmlns:m="http://iec.ch/TC57/2007/profile#">
<xs:annotation/>
<xs:element name="Profile" type="m:Profile"/>
<xs:complexType name="Profile">
<xs:sequence>
<xs:element name="Breaker" type="m:Breaker" minOccurs="0" maxOccurs="unbounded"/>
And the XML/RDF:
<!-- CIM XML Output For switch783:(295854688) -->
<cim:Switch rdf:ID="Switch_295854688">
<cim:IdentifiedObject.mRID>Switch_295854688</cim:IdentifiedObject.mRID>
<cim:IdentifiedObject.aliasName>Switch_295854688</cim:IdentifiedObject.aliasName>
<cim:ConductingEquipment.phases
rdf:resource="http://iec.ch/TC57/2009/CIM-schema-cim14#PhaseCode.ABC" />
<cim:Switch.circuit2>0001406</cim:Switch.circuit2>
<cim:Equipment.Line rdf:resource="#Line_0001406" />
You could iterate through the RDF statements and populate your JAXB beans via a Bean population utility like BeanUtils.
Iterate the statements in such a form that statements with the same subject are processed in a group. The rdf:type statements define which Class to instantiate and the rest can be probably mapped to properties of the created beans.
If you are familiar with Java reflection then this is probably quite straightforward.
What isn't clear from your post is any mapping between the XSD components and the particular resource data you have in RDF (or schema thereof, such as RDFS or OWL, or both).
If you understand this mapping, then given you have a JAXB implementation to create Java objects already (with a view to populate them with the data represented as RDF) and a Jena implementation to parse the RDF/XML in Java, then I suggest that you can implement a Java 'bridge' - effectively custom code that queries the Jena model of the RDF data to map it into new objects of the classes as generated by JAXB, which can then be marshaled to the required XML.
If you'd rather not write any Java code at all to do this, you could write some XSLT or XQuery to transform your RDF/XML directly into the required XML, but this sounds like it will be more work than the aforementioned option given what you've got already.
Do the Resource/Subject/etc objects not have any methods for converting to DOM Element?
Alternatively (not the neatest solution for sure) what about serializing to string and reading the string then using the JAXB-created (from XSD) objects' setter methods??
I have two schemas A and B with a circular dependency (it's an intermediate step). The XML files I'm using as input validate against the schema according to xmllint and Visual Studio. Eclipse is telling me that both schemas contain two global components with the same name.
A.xsd:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-Instance"
targetNamespace="http://foo.org/A"
xmlns="http://foo.org/A"
elementFormDefault="unqualified"
attributeFormDefault="unqualified">
<xs:import schemaLocation="b.xsd" />
B.xsd:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-Instance"
xmlns:foo="http://foo.org/A"
elementFormDefault="unqualified"
attributeFormDefault="unqualified">
<xs:import namespace="http://foo.org/A" schemaLocation="a.xsd" />
The XSD I'm passing to the Unmarshaller is A.xsd. When it encounters an element defined in B.xsd, it complains:
org.xml.sax.SAXParseException: cvc-elt.1: Cannot find declaration of element 'foo'.
I've set the schema via (pseudo):
InputStream in = .. A.xsd
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
return factory.newSchema(new StreamSource(in);
Can anyone explain what I'm doing wrong? Thanks.
<xs:import> is used to import namespaces defined in other schema into the current schema. The schemaLocation attribute is nothing more than a hint as to where to find that other namespace.
In the case of B.xsd, you're saying that you want to import the namespace http://blah.org, and that that namespace is handled by the schema in A.xsd.
In the case of A.xsd, your import of B.xsd is not specifying which namespace you're importing.
If A.xsd and B.xsd are representing different namespaces, then the import needs to specify that explicitly.
If, on the other hand, you're just trying to inline the elements from another schema file, in the same namespace, then the include directive is more appropriate.
edit: OK, having seen your schema fragments, I can say that <xs:import> is definitely not the right thing to do. Both A.xsd and B.xsd are defining elements in the same namespace (http://foo.org/A), and so you should be using <xs:include> instead.
When Java encounters an <xs:import>, and the namespace of that import is a namespace that it already knows about, then it effectively ignores it. So as it's parsing B.xsd (in namespace http://foo.org/A), and it finds an import for that same namespace, it ignores it.