XML inside an string element vs independent elements - java

What are the conceptual and technical disadvantages of this request/response structure:
A)
<xs:element name="OrderRequest">
<xs:complexType>
<xs:sequence>
<xs:element name="OrderID" type="xs:integer"/>
<xs:element name="OrderType" type="xs:integer"/>
<xsd:element name='OrderAttributes' type='xsd:string'/>
</xs:sequence>
</xs:complexType>
</xs:element>
where OrderAttributes element will contain string in the following XML structure:
<OrderName> xy </OrderName>
<OrderDate> xy </OrderDate>
<OrderDetails> xy </OrderDetails>
....lots of other attributes
compared to this request/response structure
B)
<xs:element name="OrderRequest">
<xs:complexType>
<xs:sequence>
<xs:element name="OrderID" type="xs:integer"/>
<xs:element name="OrderType" type="xs:integer"/>
<xsd:element name="OrderAttributes">
<xs:complexType>
<xs:sequence>
<xs:element name="OrderName" type="xs:string"/>
<xs:element name="OrderDate" type="xs:date"/>
<xs:element name="OrderDetails" type="xs:string"/>
....lots of other attributes
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
I need to design web service interface for orders processing, and I am thinking about the two alternatives mentioned above.
Version A, is more generic, so interface doesn't need to change, when OrderAttributes structure changes in any way.
But schema validation is not possible.
And my question is, what are other disadvantages compared to version B. I am analyst, not programmer, so I cannot say, if there is some impact on parsing requests, generating code from contract etc...

First note that your generic use of the word attribute to refer to a property can be confusing in XML, where attribute refers to a specific construct that stands apart from element:
<element attribute="attribute value">
<childElement>child element value</childElement>
</element>
Then, while doing design, you might consider which properties you wish to represent as XML attribute and which you wish to represent as XML elements. See XML attribute vs XML element for help deciding.
Regarding your A vs B proposed designs, note that A simply is not viable -- you cannot have unescaped markup within an element declared to have xs:string content as you've shown. Furthermore, A would then require further parsing of the OrderAttributes contents anyway whereas B would leverage the XML parser to process OrderAttributes contents. (And, like you said, B would not leverage XSD validation either.)
For future expansion, consider instead the use of xs:any, which supports various interpretations of wildcard contents via its processContents attribute values of strict, lax, or skip.

Related

Validation matcher for xml sequence elements in Citrus

I have a question regarding the correct usage of the Citrus validation matchers. In the official XML example there is the following XSD schema (TodoList.xsd) defined for a getTodoListResponse:
<xs:element name="getTodoListResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="list">
<xs:complexType>
<xs:sequence>
<xs:element name="todoEntry" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="id" type="xs:string"/>
<xs:element name="title" type="xs:string"/>
<xs:element name="description" type="xs:string" minOccurs="0"/>
<xs:element name="attachment" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element name="cid" type="xs:string"/>
<xs:element name="contentType" type="xs:string"/>
<xs:element name="data" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="done" type="xs:boolean" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
The validation matcher that is defined looks like this (templates/getTodoListResponse.xml):
<todo:getTodoListResponse xmlns:todo="http://citrusframework.org/samples/todolist">
<todo:list>
<todo:todoEntry>
<todo:id>#ignore#</todo:id>
<todo:title>${todoName}</todo:title>
<todo:description>${todoDescription}</todo:description>
</todo:todoEntry>
</todo:list>
</todo:getTodoListResponse>
But when running the test multiple times via mvn verify there are multiple todoEntry elements in the resulting XML. In order to check this variable list of XML elements that come back in the result. Therefore the check will fail.
The question is, if there is a way to express this dynamic list via the XML validation matcher API.
I got a working solution which is based on the groovy validator like this:
assert root.list.children().size() > 1 (getTodoListResponseValidator.groovy)
But I would rather like to see this working through the XML validation. It seems there is something similar called #matchesXml(), but from the docs it is not clear for me if this is suitable for the described use case.
Thx in advance.
Bye
Mario
Bottom line this is just a bad designed test for the todo-list demo. Integration tests should always operate on a well-known state of the application under test. And the tests should always leave a clean state for other tests to come. These principles are violated in that particular sample.
In fact the sample that you mention is just a demo and therefore not written as a full qualified real world example. Following from that the tests are not working when executed multiple times.
To fix this I would recommend to clear the todo list in a before-test step so you always operate on an empty list. Another possibility would be to use XPath validation instead of comparing the complete list of entries. The XPath validation can check the amount of list entries to be greater that zero for instance (just like you did in the groovy script).
In addition to that you could write a XPath expression that only validates the last entry in that list of todos returned by the server. Something like that
<validate path="count(//todo:todoEntry)" value="#greaterThan(0)#" result-type="number"/>
<validate path="//todo:todoEntry[last()]/todo:title" value="${todoName}"></validate>

Create XML on JAVA

I need to create an XML on JAVA but for multi fields on one element:
<cities>
<city_insert city_id="123" city_name="São Paulo" />
<city_insert city_id="456" city_name="Rio de Janeiro"/>
</cities>
As you can see on the example above, the element city_insert need to have city_id, and city_name , one element can have multiples fields.
How this can be done on Java?
I've searched for DOM and JDOM parsers but still don't know how this works.
Thank you!
Refer to this question for creating an XML using DOM parser.
Create XML file using java
In order to create an attribute (which you mentioned as fields), call setAttribute() method.
nodelist = doc.getElementsByTagName("city_insert");
for (Element element : nodelist) {
Element parent = element.getParentNode()
parent.setAttribute("city_id", "123");
parent.setAttribute("city_name", "São Paulo");
}
I allways do this things using jaxb
First, generate an xsd from your xml (there are many free online generators on the net)
For your xml, an online generated xsd look as follows:
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="cities">
<xs:complexType>
<xs:sequence>
<xs:element name="city_insert" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:short" name="city_id" use="optional"/>
<xs:attribute type="xs:string" name="city_name" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Then, using jaxb (many IDE's like Eclipse have an easy way of doing it) generate jaxb classes from an xsd:
Click finish, then this is java console output:
parsing a schema...
compiling a schema...
com\erax\xml\test\xsd\Cities.java
com\erax\xml\test\xsd\ObjectFactory.java
And the generated classes:
Then just use jaxb marshalling to serialize and deserialize

Remove xsd element when converting xsd to java using jaxb

I'm going to generate java code from the xsd. I want to know how to remove xsd element when converting xsd to java using jaxb. My goal is to ignore message
Ex:
<xs:element name="note">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:string" name="name"/>
<xs:element type="xs:string" name="message"/>
</xs:sequence>
</xs:complexType>
</xs:element>
Java Variables
#XmlElement
protected String name;
In here you can see that message element got removed. I want to know how to do that?
If I understand you correctly, to sum it up you want to ignore a mandatory element and still want the result to validate correctly. My short answer is that this is contradictory and does not make sense. JAXB is built to do it correctly and you want do it wrongly(?).
You have several options, eg.
Live with the extra constructor argument.
Generate no-arg constructor instead.
Don't generate, but hand code JAXB annotated classes. Maybe turn off some validation.
Don't use JAXB, use something else (dom4j et. al.) or handcraft the xml
Possibly you can add some overriding in a binding file or even a plug-in, but I wouldn't think it was worth it.
Can you alter the .xsd ?
The current Element "note" tells that both "name" and "message" are mandatory. If you want "message" to be conditional you probably need to add minOccurs="0" attribute:
<xs:element name="note">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:string" name="name"/>
<xs:element type="xs:string" name="message" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:element>

How to influence class generation of group declarations with XJC

We have the following problem. We try to generate Java code from XSD files that contain group declarations and multiple group references to these group declarations. Here a simplified version:
<xs:group name="Information">
<xs:sequence>
<xs:element name="Name">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="updated" type="xs:boolean"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:group>
<xs:element name="Address">
<xs:complexType>
<xs:sequence>
<xs:group ref="Information" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Customer">
<xs:complexType>
<xs:sequence>
<xs:group ref="Information"/>
</xs:sequence>
</xs:complexType>
</xs:element>
The main points are:
Each of these elements is defined in its own file
The same group Information is references twice
There is no separate type for the group
There is also no separate type for the Name element inside the group
We cannot change the XSD file
The problem we face now is that xjc generates non-deterministically depending on the machine where we build, sometimes the type Address.Name and sometimes the type Customer.Name, because the Name element is a complex type and requires a type.
Is there any way to tell xjc to always generate the same type?
Customize the anonymous complex type with the jaxb:class binding and specify the class name.
Use <jaxb:globalBindings localScoping="toplevel"/> to generate inner classes on the top level instead.
A combination of these two will give you a predictable class.
You could try the -episode command line option of XJC. It is primarily meant for compilation in multiple steps, but I think it basically "dumps decisions" taken by XJC during a compilation into a (binding) configuration file. If you are lucky, you find suitable settings related to the Name element/type in the episode file which you can copy into your binding configuration file to make XJC behave deterministically.

regarding xsd schema defination of type attribute in response xml

Thanks for your time , newbie in java,
<address type="sponsor">
<fullAdress>
<street>Blah blah</street>
<country>Blah blah</country>
</fullAdress>
</address>
this is what my end user xml would be , i was little confused about attribute type over here.. what would be xsd definition?
Judging from what you asked, my understanding is that you are asking about the types of your attributes. I have not used XSD extensively but here is what I think you are looking for.
<xs:element name="fullAddress">
<xs:complexType>
<xs:sequence>
<xs:element name="street" type="xs:string"/>
<xs:element name="country" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
Obviously there is more setup involved with the file itself (This would be a snippet) as far as declarations and such are concerned. But as you can see I specified both the street and country attributes as String types.
Hope this helped. :)

Categories