order of parsed elements is lost in XMLBeans - java

I have a XML structure somewhat like this:
<root>
<a/>
<b/>
<b/>
<a/>
<a/>
</root>
My XSD looks like this:
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:choice maxOccurs="unbounded">
<xs:element ref="a"/>
<xs:element ref="b"/>
</xs:choice>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="a" type="xs:string" />
<xs:element name="b" type="xs:string" />
I.e. i have a random sequence of two different sub tags.
Using XMLBeans i get a Root object with access methods:
getAArray(), getBArray()
And here's my problem:
The tags are grouped by name and the original order (a,b,b,a,a) is lost.
But i need to know the order of those elements.
What is the best / easiest way to do that with XMLBeans?

Try
xml.selectPath("./*")

ok i got it.
the selectPath method of XmlObject returns an array of objects so it gives the sequence.

Related

Java XML Create Fragment/Elements Without Namespace

I am trying to construct an XML document using org.w3c.dom.Document to create some XML for another existing tool. The problem I am having is that the tool seems to have the XML namespaces in a strange way. How can I replicate this using the Java API's?
<ns1:myroot xmlns:ns1="http://foo.com/ns1/">
<ns2:bar xmlns:ns2="http://foo.com/xml/bar/">
<ns2:bar_thing>abc</ns2:bar_thing>
</ns2:bar>
<ns3:data xmlns:ns3="http://foo.com/xml/special-ns">
<!--These are not namespaced for some reason. If I use the ns3 prefix, or
use a default xmls="...", the tool fails to load the document, saying the
elements have invalid values.
-->
<a>Element without namespace</a>
<b>
<bi>1</bi>
<bii>2</bii>
</b>
</ns3:data>
</ns1:myroot>
I can build most of the document easily with createElementNS and setAttributeNS. However I can't get the ns3:data contents to be correct.
Trying to use the non-namespace createElement still left an xmlns="http://foo.com/xml/special-ns"> on my a and b elements, as did using createElementNS with an empty namespace, and obviously a non-empty namespace puts them in a namespace.
The schema for http://foo.com/xml/special-ns has a bunch of declarations like these below, not sure what the tns thing is about, but otherwise does not seem special (although I am not 100% sure the tool actually does anything with the XSD and I don't have access to the source).
<xs:schema version="1.0" targetNamespace="http://foo.com/xml/special-ns">
<!--Bunch of xs:element such as this-->
<xs:element name="data" type="tns:data" />
<!--types declared after-->
<xs:complexType name="data">
<xs:sequence>
<xs:element name="a" type="tns:aDataObj" minOccurs="0"/>
<xs:element name="b" type="tns:bDataObj" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:simpleType name="aDataObj">
<xs:restriction base="xs:string">
<xs:pattern value="[a-zA-Z0-9 ]+" />
</xs:restriction>
</xs:simpleType>
<xs:complexType name="bDataObj">
<xs:sequence>
<xs:element name="bi" type="xs:string"/>
<xs:element name="bii" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>

xpath to rename single class in crazy hierarchy

I'm trying to generate classes from wsdl using jaxws-maven-plugin, but I get uncompilable results. The problem is this part of one of the xsds, where you can see that there are nested elements with the same name:
<xs:complexType name="TrafficCountsReplyData" abstract="true">
<xs:sequence>
<xs:element name="effectiveTrafficWindow" type="common:DateTimeMinutePeriod" minOccurs="1" maxOccurs="1"/>
<xs:element name="flows" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="item" type="flow:Flow" minOccurs="0" maxOccurs="100"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="counts" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="item" minOccurs="0" maxOccurs="1440">
<xs:complexType>
<xs:sequence>
<xs:element name="key" type="common:DateTimeMinutePeriod" minOccurs="1"
maxOccurs="1"/>
<xs:element name="value" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="item" minOccurs="1" maxOccurs="3">
<xs:complexType>
<xs:sequence>
<xs:element name="key" type="flight:TrafficType"
minOccurs="1" maxOccurs="1"/>
<xs:element name="value" type="flow:Counts" minOccurs="1"
maxOccurs="1"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
As you can see, there there are multiple elements named item. This result in multiple inner classes with the same name inside of the single class TrafficCountsReplyData
So I'm trying to put together a binding file which would rename one of them. When I try to rename the outer item in the counts element using this:
<jaxb:bindings node="//xs:complexType[#name='TrafficCountsReplyData']//xs:element[#name='counts']//xs:element[#name='item']">
<jaxb:class name="Lulz"/>
</jaxb:bindings>
I get the following error:
[ERROR] XPath evaluation of "//xs:complexType[#name='TrafficCountsReplyData']//xs:element[#name='counts']//xs:element[#name='item']" results in too many (2) target nodes
When I create the binding xpath expression for the inner one like this:
<jaxb:bindings node="//xs:complexType[#name='TrafficCountsReplyData']//xs:element[#name='counts']//xs:element[#name='item']//xs:element[#name='value']//xs:element[#name='item']">
Then I get following error:
java.lang.IllegalArgumentException: Illegal class inheritance loop. Outer class Lulz may not subclass from inner class: Lulz
I can't figure out how to make this work. Where does the inheritance come from? There's another item in the flows element, but that shouldn't be matched by the Xpath. Without the binding file, I can generate the sources. I have correct schema in the binding file, because I can for example rename the class generated by the parent element.
mmm
I had a similar issue, but with properties..
I don't ahve the full xsd to check, but provided you want to change the OUTER item tag into something else, try this one:
<?xml version="1.0"?>
<jxb:bindings version="1.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
jxb:extensionBindingPrefixes="xjc" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<jxb:bindings schemaLocation="../yourlocation/yourschema.xsd" version="1.0">
<!-- Customise the package name -->
<jxb:schemaBindings>
<jxb:package name="whatyouwant.something"/>
</jxb:schemaBindings>
<!-- rename the value element -->
<jxb:bindings node="//xs:complexType[#name='TrafficCountsReplyData']//xs:sequence//xs:element[#name='counts']//xs:complexType//xs:sequence//xs:element[#name='item']">
<jaxb:class name="Lulz"/>
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>
If this seems not to work if you can disclose the xml I should be able to help you furthe (on vacation until monday in case) , but consider that you were giving the wrong "path", jumping away a few "subelement" in your xpath expression.
Let me know.
I've found the solution here: JAXB Customizations With a Poorly Formed WSDL
I had to add /xs:complexType at the end of the Xpath. I guess it's because the root of the class is in fact the complexType and not enclosing xs:element. So it was like this:
<jaxb:bindings node="//xs:complexType[#name='TrafficCountsReplyData']//xs:element[#name='counts']/xs:complexType/xs:sequence/xs:element[#name='item']/xs:complexType">
<jaxb:class name="Lulz"/>
</jaxb:bindings>
Now I can generate classes and compile them.

How to get the right jaxb object when having two elements under one list (jaxbObj.getAoAndBo() )?

I'm using Java and JAXB for parsing a xml file.
I had a schema(xsd) that contains secquence element that contains two inner sequence element.
the xsd looks something like the following:
...
<xs:element name="product_list">
<xs:complexType>
<xs:sequence minOccurs="1" maxOccurs="unbounded">
<xs:element maxOccurs="unbounded" name="product">
<xs:complexType>
<xs:sequence />
<xs:attribute name="name" type="xs:string" use="required" />
<xs:attribute name="release" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
<xs:element maxOccurs="unbounded" name="info">
...
</xs:complexType>
</xs:element>
</xs:schema>
After unmarshalling, when I want to fetch the list of "product", I get:
product_list.getProductsAndInfo() => type: List<Object>
How can I get the information from the "product" object? (e.g product_list.getProduct)
for getting the needed object information there is a need to use casting on the list of objects, for example:
ProductList pl = new ProductList(); // xml main object/element
pl= unmarshallfunc();
((ProductList.Product)pl.getProductAndInfo().get(0)).getName(); //type: List cast to Product.

Ugly java code with xsd:sequence

I use JAXB to bind XSD schemas to POCOs. I have tried two different ways to write an XSD schema but each has a flaw:
Option 1
Problem: Each element is represented with <Elements> in XML instead of <Element>, plus they are not inside a container such as <ElementsContainer>.
XSD Schema
<xs:element name="Root" type="RootType" />
<xs:complexType name="RootType" />
<xs:sequence>
<xs:element name="Elements" type="xs:string" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
Java
RootType r = new RootType();
r.getElements.add("Str1");
r.getElements.add("Str2");
Marshaled XML
<Root>
<Elements>Str1</Elements>
<Elements>Str2</Elements>
</Root>
Option 2
Problem: Java code looks uglier.
XSD Schema
<xs:element name="Root" type="RootType" />
<xs:complexType name="RootType" />
<xs:element name="Elements">
<xs:complexType>
<xs:sequence>
<xs:element name="Element" type="xs:string" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:complexType>
Java
RootType r = new RootType();
r.getElements().getElement().add("Str1");
r.getElements().getElement().add("Str2");
Marshaled XML
<Root>
<Elements>
<Element>Str1</Element>
<Element>Str2</Element>
</Elements>
</Root>
Question: Is there a way to write a schema that outputs an XML like in Option 2 and whose code is written like in Option 1?
Edit: <xs:list> is not an option as elements may have white-spaces.
Starting from Java Classes
If you are starting from Java Objects you can use the #XmlElementWrapper annotation to add a grouping element.
#XmlElementWrapper(name="Elements")
#XmlElement(name="Element)
public List<Element> getElements() {
return elements;
}
Starting from XML Schemas
The XJC tool is very extensible. The following plug-in written for the XJC tool appears to allow you to generate #XmlElementWrapper annotations into your model.
https://github.com/dmak/jaxb-xew-plugin

Is there a java API to generate xml with an inline schema definition

I want to generate the xml file that holds its schema as well as the xml data contain using java,as per my knowledge it is possible in C# .NET.Is it possible in java???
My XML file should be look like as given below.
<transaction>
<xs:schema id="transaction" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="transaction" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="id">
<xs:complexType>
<xs:sequence>
<xs:element name="in" type="xs:string" minOccurs="0" />
<xs:element name="sn" type="xs:string" minOccurs="0" />
<xs:element name="book" type="xs:string" minOccurs="0" />
<xs:element name="author" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="data">
<xs:complexType>
<xs:sequence>
<xs:element name="dateTime" type="xs:dateTime" minOccurs="0" />
<xs:element name="key" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="productData">
<xs:complexType>
<xs:sequence>
<xs:element name="dateTime" type="xs:dateTime" minOccurs="0" />
<xs:element name="key" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
<id>
<in>computer</in>
<sn>1234567</sn>
<book>JAVA</book>
<author>klen</author>
</id>
<data>
<dateTime>2011-06-24T17:08:36.3727674+05:30</dateTime>
<key>Err</key>
</data>
</transaction>
In my given example my xml file contain data as well as schema I need to generate this type of file from schema using java.
I can only create the xml part using jaxb and main part of my code is look like as
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,true);
jaxbMarshaller.setProperty(Marshaller.JAXB_FRAGMENT,true);
jaxbMarshaller.marshal(transaction, file);
jaxbMarshaller.marshal(transaction, System.out);
but I can not add the inline xml schema part with my xml file.
#jtahlborn ok I will try to dig it up thanks for your help.I have another question I heard about that stax is better than dom to xml write,so I want to use stax is it possible to set namespace and other thing. I have another question is it true that jaxb is only use to convert xml to xml schema(un marshaling) and xml schema to xml(marshaling) and if I need to write xml file then we need to use jaxb[DOM,STAX(stream based reading writing),SAX(stream only reading)] .
You would:
create a DOM document from your schema (e.g. parse the schema file)
create a new DOM document
add the root node to your new DOM document (e.g. "transaction")
append the schema document from step 1. as the first child of the "transaction" element
append the actual document data as subsequent children of the "transaction" element
Alternately, if you want to use JAXB to generate the "main" xml output, then you can:
populate jaxb models (created from the schema)
marshal the jaxb models to a DOM document
create a DOM document from your schema (e.g. parse the schema file)
insert the schema document from step 3. as the first child of the "transaction" element in your DOM document
(with a few jaxb config tricks, you could probably get your Transaction model to have an Element "schema" property, and then you could set that property from the parsed schema doc and marshal the whole model at one time)

Categories