Determine the order of xml mixed content in derived class - jaxb

I have the schema like this :
<xsd:complexType name="ContentType" mixed="true">
<xsd:annotation>
<xsd:documentation><![CDATA[
The content type is a broad base type allowing any content.
]]></xsd:documentation>
</xsd:annotation>
<xsd:complexContent>
<xsd:extension base="BaseContentType">
<xsd:sequence>
<xsd:any minOccurs="0" maxOccurs="unbounded" namespace="##any" processContents="lax"
/>
</xsd:sequence>
<xsd:attribute name="orientation" type="OrientationEnum" use="optional"
default="portrait">
<xsd:annotation>
<xsd:documentation><![CDATA[
The #orientation attribute is used to specify a "landscape"
orientation for the published form. This is primarily used
for schedules or for tables.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
I use xjc command line tool to generate the Java classes from the above schema and the classes are generated as follows:
public abstract class BaseContentType {
#XmlMixed
protected List<Serializable> content;
#XmlAttribute(name = "id")
#XmlJavaTypeAdapter(CollapsedStringAdapter.class)
#XmlID
#XmlSchemaType(name = "ID")
protected String id;
and
public class ContentType
extends BaseContentType
{
#XmlMixed
#XmlAnyElement(lax = true)
#OverrideAnnotationOf
protected List<Object> contentOverrideForContentType;
When I unmarshall, all the nested xml elements get populated in the List contentOverrideForContentType of the ContentType object and all the text elements get populated in the List content of BaseContentType.
How do I determine the order of the text elements with respect to the nested elements and construct the entire text?
I am trying to get the entire text within the ContentType for which I have to look at top level text and the text of all the nested tags and combine them all(here is where I need to know the order). Is there a better way to just extract all the text from ContentType?
Thanks!
EDIT
This is related to this question.

If you declare a propOrder on the specific jaxB class you can specify the order that objects will appear in the xml
e.g.
#XmlType(propOrder = {
"firstObjectName",
"fsecondObjectName"
})
note: when using a propOrder all elements in the object must be added to the propOrder.

I had the same issue and I found out that the elements will be ordered following the order in which the elements had been added to the list ... this is assuming you are using an ordered list (List, ArrayList...)

Related

jxpath not honoring JAXB's XmlElement name of xjc-generated classes

I use an XML Schema Definition and JAXB to generate Java classes with proper #XmlElement or #XmlRootElement annotations.
Since the schema has some deep nesting in it (not my choice), I'd rather use jxpath to access deeply buried classes using an XPath (rather than cumbersome daisy-chain of .getThat() and that != null).
The problem is that some of the XML element names contain dashes, e.g. foo-bar. When I try to access elements using org.apache.jxpath, I need to rewrite my XPath so that such names are camel-cased instead (fooBar) like the name of the actual Java objects. Is there any way to tell jxpath to find the elements using the XPath corresponding to the XML element names (instead of the camel-cased Bean names)?
I think it is related to this question, however in my case I don't actually case what kind of tricks and decorations are used on the auto-generated classes, as long as xjc can do it.
Here is a simple example to illustrate the issue.
First, a small XSD file:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="record">
<xs:complexType>
<xs:sequence>
<xs:element name="foo-bar" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Compile it...
xjc -p org.pd.jx example.xsd
Here is the xjc-generated Record.java class (minus comments):
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {"fooBar"})
#XmlRootElement(name = "record")
public class Record {
#XmlElement(name = "foo-bar", required = true)
protected String fooBar;
public String getFooBar() {return fooBar;}
public void setFooBar(String value) {this.fooBar = value;}
}
Then, trying to access the data via jxpath (in practice I have to deal with lots of deeply nested classes), one can see below that the correct XPath ("foo-bar") doesn't work, but a camel-cased version does.
Record record = new Record();
record.setFooBar("hello world");
JXPathContext context = JXPathContext.newContext(record);
context.setLenient(true);
String a = (String)context.getValue("foo-bar", String.class); // is null
String b = (String)context.getValue("fooBar", String.class); // "hello world"
I believe JXPath operates on an objects properties and not the XML elements they correspond to. I do not believe that JXPath parses any of the JAXB metadata so it wouldn't know the XML nodea you have mapped. What you are seeing appears to be the expected behaviour.

How to extract content from xsd appinfo element in java

I have an xsd with annotation elements that in turn contain the appinfo element. I am using the appinfo element to pass in the some custom information about the schema and need to extract the contents of the appinfo while I am traversing through the element.
Snippet from the xsd.
<xsd:element name = "Entity">
<xsd:annotation>
<xsd:appinfo>EntityReference</xsd:appinfo>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element
minOccurs = "0"
name = "Id"
type = "tns:guid"/>
<xsd:element
minOccurs = "0"
name = "LogicalName"
nillable = "true"
type = "xsd:string"/>
<xsd:element
minOccurs = "0"
name = "Name"
nillable = "true"
type = "xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
This is the code that I am using to extract the application information from the annotation.
SchemaAnnotation annotation = element.getAnnotation();
if(annotation!=null){
XmlObject[] ai = annotation.getApplicationInformation();
for(XmlObject obj : ai){
if(obj!=null){
//System.out.println(obj.toString());
obj.getDomNode().getNodeValue();
}
}
}
But I get a null value. The obj.toString() however returns this
<xml-fragment xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:request="http://ns1" xmlns:tns="http://ns2">EntityReference</xml-fragment>
How do I get the content "EntityReference" from appinfo? Am I suppose to write a custom handler to parse the string content?
Thanks
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document document = builder.parse(new ByteArrayInputStream(obj.toString().getBytes()));
NodeList list = document.getChildNodes();
Node node = list.item(0);
if (node.getFirstChild() != null
&& node.getFirstChild().getNodeType() == Node.TEXT_NODE) {
//Text tn = (Text) node.getFirstChild();
System.out.println(node.getFirstChild().getTextContent());
}

jaxb unmarshalling giving NULL to anytype element in xsd

I am getting NULL value eventhough there is some value in xml using jaxb unmarshalling.
Element in xsd
<xs:element name="Account" minOccurs="1" maxOccurs="unbounded" >
does not have type attribute.
In its respective Java class AccountNo become java.lang.Object type.
but after Unmarshalling xml
<AccountNo>GDF23232223</AccountNo>
output comes [AccountNo=NULL]
My unmarshalling code
jaxbContext = JAXBContext.newInstance("net.process");
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
document = (Document) jaxbUnmarshaller.unmarshal(inputFile);
can you help me?
Thanks
I struggled with the same problem. Try to get the value using
element.getFirstChild().getNodeValue()
There I got the correct value

Are the both schemas equivalent?

1.
<xsd:element name="tuple">
<xsd:complexType>
<xsd:sequence>
<xsd:any minOccurs="0" maxOccurs="unbounded" namespace="##any" processContents="skip" />
</xsd:sequence>
</xsd:complexType>
2.
<xsd:element name="tuple"/>
Are the both above schemas equivalent?
Please help
NO! They aren't same!
In first schema: element <tuple> can have 0 or more elements under it with/of any name, that is because you have added <any> tag with minOccurs="0" and maxOccurs="Unbounded" under complexType definition of element tuple
Also Since you have specified processContents="skip" under <any> it doesn't bother anything about its child elements..
Example:
<tuple>
<foo>data</foo>
<bar foobarattribute="foobardata">data</bar>
</tuple>
As you can see, though foo and bar and its attribute foobarattribute are not defined in XSD, it allows this XML as valid. But it doesn't allow attribute under <tuple>
EDIT:
Second schema:
It is as same as declaring the type as anyType
<xsd:element name="tuple" type="xs:anyType"/>
Which means it allows any element and any attribute under tuple. The sample XML would be like:
<tuple foo="bar">
<foobar attrb="value">data</foobar>
</tuple>
You can observe that unlike first sample XML, this has attribute under <tuple> as well.
One more important difference between two sample XSD code is:
In 1st code you are specifying processContents as "skip": Because of which XML processor does not attempt to validate any elements from the specified namespaces..
In the 2nd Code, for anyType, processContents would be "lax": because of which the XML processor tries to obtain the schema for the required namespaces and validate the elements.
Hope it helps..

How to convert XSD Simple Type to rdfs:Datatype using Jena

Suppose I have an XSD file having below lines of code;
<xsd:simpleType name="test">
<xsd:restriction base="xsd:string">
<xsd:maxLength value="50" />
</xsd:restriction>
</xsd:simpleType>
What I am trying to do is to convert this xsd simple type into an instance of rdfs:Datatype in an ontology. Below is what I want.
<rdfs:Datatype rdf:about="http://www.example.org/example1/#testDatatype">
<rdfs:subClassOf rdf:resource="http://www.w3.org/2001/XMLSchema#string"/>
<owl:equivalentClass>
<rdfs:Datatype>
<owl:onDatatype rdf:resource="http://www.w3.org/2001/XMLSchema#string"/>
<owl:withRestrictions rdf:parseType="Collection">
<rdf:Description>
<xsd:maxLength rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
>50</xsd:maxLength>
</rdf:Description>
</owl:withRestrictions>
</rdfs:Datatype>
</owl:equivalentClass>
</rdfs:Datatype>
How do I do this using Jena?
Turns out I can do this with the below code. I parse XSD with XSOM. Assume that I stored "test" simpletype in a variable called "simple" (XSSimpleType).
String URI = simple.getTargetNamespace() + "#" + simple.getName() + "Datatype";
OntModel ontology = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM);
OntClass datatype = ontology.createOntResource(OntClass.class, RDFS.Datatype, URI);
Resource onDatatype = XSD.xstring;
OntClass equivClass = ontology.createOntResource(OntClass.class, RDFS.Datatype, null);
equivClass.addProperty(OWL2.onDatatype, onDatatype);
datatype.addEquivalentClass(equivClass);
It is not a complete code and it does not include the code segment related with parsing XSD but I hope it will give the idea.

Resources