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>
Related
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>
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
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)
I've got something like the following XML file.
<credits>
<property name="tag">
<item>v0003</item>
</property>
<property
name="tag">
<item>mhma03h</item>
</property>
</credits>
First requirement is that this XML cannot change no matter what. Please don't suggest doing that below.
I need to write a schema that validates this. And Java code that does the validation.
I am completely stuck and I have no idea really what is going on.
What's a schema like this look like? I've gotten one but it's so bad I'm not going to bother posting. :P I don't want to have to append a namespace to the XML elements. They're set in stone.^_^
How do I just make it so all of these elements are just "found" by the parser? Can I just tell it ignore all this namespace nonsense. With this application of validating against a schema, namespace conflicts are simply impossible.
I've tried putting
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="books" elementFormDefault="unqualified">
for my namespace info and
UPDATE: I've updated what I'm doing to reflect the answers given so far! :)
XSD
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="property">
<xs:complexType>
<xs:sequence>
<xs:element ref="item"/>
</xs:sequence>
<xs:attribute name="name" use="required">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="tag"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
<xs:element name="item">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="mhma03h"/>
<xs:enumeration value="v0003"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="credits">
<xs:complexType>
<xs:sequence>
<xs:element ref="property" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
XML
v0003
Code to load and validate yes. Before you ask, the files are able to be loaded. I've checked like 20 times. :P
SAXParserFactory factory = SAXParserFactory.newInstance();
SchemaFactory schemaFactory =
SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
factory.setSchema(schemaFactory.newSchema(
new Source[] {new StreamSource("small.xsd")}));
javax.xml.parsers.SAXParser parser = factory.newSAXParser();
org.xml.sax.XMLReader reader = parser.getXMLReader();
reader.setFeature("http://xml.org/sax/features/validation", true);
reader.setFeature("http://apache.org/xml/features/validation/schema", true);
reader.parse(new InputSource("small.xml"));
Here is a schema that corresponds to the XML file you posted:
<?xml version="1.0" encoding="UTF-8"?>
<!--W3C Schema generated by XMLSpy v2011 sp1 (http://www.altova.com)-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="property">
<xs:complexType>
<xs:sequence>
<xs:element ref="item"/>
</xs:sequence>
<xs:attribute name="name" use="required">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="tag"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
<xs:element name="item">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="mhma03h"/>
<xs:enumeration value="v0003"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="credits">
<xs:complexType>
<xs:sequence>
<xs:element ref="property" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
This may not correctly capture the requirements for each element and attribute (check that the min/max occurs, required/optional proprerties, etc... are set correctly) but it should get you started on working with an XML schema that will validate correctly. The schema does not define a target namespace so you won't have to worry about modifying the existing XML to add in namespace prefixes to your existing elements.
You need to find a way to tell the XML processor to use your namespace as the default when it is processing a document without an explicit namespace. Most processors have a way to do this, IIRC there is a method named setNoNamespaceSchema or something similar. You would write an XML schema with a namespace and tell the processor (validator, whatever) to use your namespace for documents that do not have an explicit namespace.
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.