I'm developing a plugin that has node(computer) objects with attributes like:
String name
String description
String labels
Launcher computerLauncher
...
I can convert the node(computer) object to an XML-formated String like:
String xml = jenkins.instance.toXML(node);
Which gives me a string:
<name>Computer1</name>
<description>This is a description</description>
<labels>label1 label2</labels>
<launcher>windows.object.launcher.12da1</launcher>
Then I can go the other way back:
Node node = jenkins.instance.fromXML(xml);
I have no methods for changing attributes in a Node so I want to convert it to XML, change som attributes and then make it a Node again.
I see two options
Manipulate the XML with some String methods to replace everything in between the <> tags.
Try to cast the XML string to something like a real Object and manipulate it that way.
Not sure what would be the best approach.
Why invent something new when there already is support for all that using Java's DOM (Document Object Model) API?
Use a DocumentBuilderFactory to get a DocumentBuilder and create a Document instance. With this you can create the 'Node' objects (please note that the example you posted is actually not valid XML, it's missing a root node) in your toXML method, serializing the Document to a String could be done by using a Transformer.
With the DOM API you can also modify the attributes of your existing elements.
Parsing the Document instance from an XML string is realized again with the help of the DocumentBuilder, using DocumentBuilder#parse.
If your DOM operations are not too complex this should be a nice, quick way to accomplish your goal.
It makes sense to me to use a DOM-like approach. But don't use DOM itself: there are much better alternatives like JDOM and XOM that have much friendlier APIs.
recenty I had to manipulate large XML files (my software had to create some XML files dynamically and get input data from some other XML files). To do this I've used JAXB, which is a very neat API that marshalls XML files into Java objects and Java objects into XML files automatically.
However to do this I had to create a XSD file to specify the XMLs that I would need to read and write from.
Therefore JAXB requires more work to set up than DOM, so if your needs are simple I suggest that you use DOM, however if your needs are more complex, then I would suggest JAXB.
Related
I'm working on a project which requires me to insert values into a predefined XML template. Till now I have been using the StringBuilder class to convert the XML file into a string and make the required changes. Now, I wanted to know whether using an XML Parser like DOM,JDOM, SAX etc would be more efficient compared to the alternative way I'm using.
Since there are no implementation issues, I don't think any piece of code needs to be shared.
Please see this it may help you:
https://www.mkyong.com/java/how-to-modify-xml-file-in-java-dom-parser/
Modifying an XML document by string replacements in general is a bad practice as you can accidentally make your XML invalid, so for your task I would rather use simple XSL transformation.
There is a .net version of this question answered here: XML input/output with Fitnesse
I need to do that with the Java version of Fitnesse and there doesn't seem to be anything similar. I have some tests that accept XML and return XML so I need both the input and the expected output to handle XML in the fields. I've tried various html escaping, but that doesn't seem to get the job done on the comparison side of things. The XML is arbitrary, so I can't parse it into domain objects and compare individual fields (well, I could, but there'd be tons of different object mappings).
Anyone find a way to deal with this issue in a generic way? A custom Java equivalent of the .net solution that exists somewhere?
Not sure if this is best solution. You may want to use some XML frameworks e.g. XStream which has very simple API to convert XML into JAVA objects. Using this, you may want to convert both XML files in JAVA and use JAVA comparison.
Simple steps would be:
Define simple Java object (POJO) e.g. MyXMLObj to map the XML attributes in Java attributes.
Create/generate equals method in the above POJO class MyXMLObj.
Convert your XMLs in Java as :
XStream xstream = new XStream();
XStream xstream = new XStream(new DomDriver());
//or
//XStream xstream = new XStream(new StaxDriver());
MyXMLObj myXMLObj1= (MyXMLObj)xstream.fromXML(xml1);
MyXMLObj myXMLObj2= (MyXMLObj)xstream.fromXML(xml2);
Simply compare the two objects as:
if(myXMLObj1.equals(myXMLObj2)){
System.out.println("Matching");
}else{
System.out.println("Not Matching");
}
I encountered something similar where xml response could change in future or doesn't confirm to a particular style all the time, or xml is not returned as an xml object rather a string is returned etc.
I wrote a generic fixture that would take an xml string and parse it to give us an xml doc object. I would also capture the xml element path and expected value from the wiki and I confirm if expected value is what is stored in the xml or not using xpath.
!|ValidateXmlValue |
|xmlString|xmlElem |getXMLvalue? |
|$respBody|/root/childnode1/ |${variable} |
This way users have the flexibility to query node value by simply giving the full path to that node and compare it against an input variable etc. Even if something changes, only test will need to change (you can store path to each xml element in a variable as well, as part of set-up step)
I am getting object of type org.w3c.dom.Document from a source (basically a parsed xml document - java object). I want to use this xml document object to create java objects using JAXB. How can I do that?
You can unmarshal directly from DOM objects, this includes a org.w3c.dom.Document:
http://docs.oracle.com/javase/6/docs/api/javax/xml/bind/Unmarshaller.html#unmarshal%28org.w3c.dom.Node%29
If you need to specify the type of object you are unmarshalling, then you can wrap the DOM node in a javax.xml.transform.dom.DOMSource and use the following API:
http://docs.oracle.com/javase/6/docs/api/javax/xml/bind/Unmarshaller.html#unmarshal%28javax.xml.transform.Source,%20java.lang.Class%29
From the top of my head you could just convert the Document to a Stream and use the Unmarshaller to convert to the JAXB instance you need.
Something like:
MyJAXB o = (MyJAXB)unmarshaller.unmarshall(new StringReader(arrayoutsream.tostring()));
Disclaimer: Haven't even bothered to see if this compiles but you should understand how to approach this
This is a design question rather than a Java-specific question, but I'm designing it for Java.
I've been writing some XML pull parsing classes to handle a custom XML response and as I design them, I can't help but think whether there's something better. Maybe someone even has a design pattern for it.
So, here's what my XML may look like:
<ResponseRoot>
<Header>
<RequestId />
<OtherHeaderMetaData />
</Header>
<Body>
...
<!-- Lots of other elements and nested elements -->
...
</Body>
</ResponseRoot>
So depending on the RequestId (a key of sorts), the Body element is different. Given that this is pull parsing, I'd have a large switch statement and lots of if-else-if blocks.
Would it be more efficient for one class with lots of static methods to handle the whole XML stream, or would it make for a better design to have one class responsible for each RequestId?
I was thinking of mapping RequestId to a class name, and then when I hit Body, I use a factory to retrieve the appropriate subparser. Inside that factory, I could even use a mapping of Class instances and use reflection to instantiate the appropriate parser (since not all parsers are needed all the time). Or... use reflection to grab the appropriate static parsing method instead, so I don't need to instantiate parsers that are really just 1-use classes...
Yea, I'm thinking too deeply, but since this is just a personal project, I just got curious about how people design parsing classes around a StAX parser.
So depending on the RequestId (a key of sorts), the Body element is different.
Can you redesign the XML so that a valid body elemt does not depend on the request-ID, but is determined entirely by the surrounding response element? Then document validity (conformance to the DTD) would correspond to message response validity.
Instead of using a switch statement, consider using the state design pattern. That is, implement your document handler as a finite state machine.
I'd definitely go for a separate processor class per request type. Your factory approach sounds good, but don't bother with the reflection stuff, just create those processor objects instead of using reflection, thirty-something bytes of heap space are a very reasonable price for easily readable code.
One thing that is important though with StAX that in the documentation of every processing method you should describe what state that method is expecting the input to be in (e.g.: before or after having processed the opening <body> tag) and where does it leave the input after processing. You can save yourself hours of frustrating debugging this way.
Instead of putting the responsibility of parsing each custom XML object on the StAX parser, why not have the StAX parser create an intermediate representation of the XML object? Then, you could have a factory which would construct a final representation of the XML object using the RequestID. The code would look similar to:
IntermediateObject io = StAX.parse(XML);
FinalObject = Factory.create(io.getRequestID, io);
The upside of using this approach is that you're separating responsibilities. The StAX parser will only parse the XML, while the factory would be responsible for doing further processing with that information.
I know this isn't really what XPath is for but if I have a HashMap of XPath expressions to values how would I go about building an XML document. I've found dom-4j's
DocumentHelper.makeElement(branch, xpath) except it is incapable of creating attributes or indexing. Surely a library exists that can do this?
Map xMap = new HashMap();
xMap.put("root/entity/#att", "fooattrib");
xMap.put("root/array[0]/ele/#att", "barattrib");
xMap.put("root/array[0]/ele", "barelement");
xMap.put("root/array[1]/ele", "zoobelement");
would result in:
<root>
<entity att="fooattrib"/>
<array><ele att="barattrib">barelement</ele></array>
<array><ele>zoobelement</ele></array>
</root>
I looked for something similar a few years ago - a sort of writeable XPath. In the end, having not found anything, I hacked up something which essentially built up the XML document by adding new nodes to parent expressions:
parent="/" element="root"
parent="/root" element="entity"
parent="/root/entity" attribute="att" value="fooattrib"
parent="/root" element="array"
parent="/root" element="ele" text="barelement"
(This was itself to be governed by an XML configuration file, hence the appearance of above.)
It would be tempting to try an automate some of this to just take the last path element, and make something of it, but I always felt that there were XPath expressions I could write which such a dumbheaded approach would get wrong.
Another approach I considered, though did not implement (the above was "good enough"), was to use the excellent Jaxen to generate elements that did not exist, on the fly if it didn't already exist.
From the Jaxen FAQ:
The only thing required is an implementation of the interface org.jaxen.Navigator. Not all of the interface is required, and a default implementation, in the form of org.jaxen.DefaultNavigator is also provided.
The DOMWriterNavigator would wrap and existing DOMNavigator, and then use the makeElement method if the element didn't exist. However, even with this approach,
you'd probably have to do some pre/post processing of the XPath query for things like attributes and text() functions.
The best I was able to come up with is to use a JAXB implementation, which will marshall/unmarshal objects to xml and then I used Dozer (http://dozer.sourceforge.net/documentation/mapbackedproperty.html) to map the xpaths which were keys in a map to the JAXB object method setters.
<mapping type="one-way" map-id="TC1">
<class-a>java.util.Map</class-a>
<class-b>org.example.Foo</class-b>
<field>
<a key="root/entity/#att">this</a>
<b>Foo.entity.att</b>
<a-hint>java.lang.String</a-hint>
</field>
It's more of a two step solution, but really worked for me.
I also wanted same kind of requirement where nature is so dynamic and dont want to use XSLT or any object mapping frameworks, so i've implemented this code in java and written blog on it please visit,
http://ganesh-kandisa.blogspot.com/2013/08/dynamic-xml-transformation-in-java.html
or fork code at git repository,
https://github.com/TheGanesh/DynamicXMLTransformer