Merging different nodes of multiple XML files using JAVA - java

I have some xml files in an arrayList, for example A.xml B.xml
and I want to merge some of the nodes while the rest to remain as are using java. I'm new at using so I don't know how to do.
A xml:
<?xml version="1.0" encoding="UTF-8"?>
<nta>
<declaration>
bool A, B;
bool C;
</declaration>
<template>
<location id="1" x="10" y="10"/>
<transition>
<source ref="3"/>
</transition>
</template>
<system> system AND;</system>
</nta>
B.xml:
<?xml version="1.0" encoding="UTF-8"?>
<nta>
<declaration>
int f,k;
bool D;
</declaration>
<template>
<location id="100" x="40" y="89"/>
<transition>
<source col="9"/>
</transition>
</template>
<system> system OR;</system>
</nta>
And the output:
<?xml version="1.0" encoding="UTF-8"?>
<nta>
<declaration>
bool A, B;
bool C;
int f,k;
bool D;
</declaration>
<template>
<location id="1" x="10" y="10"/>
<transition>
<source ref="3"/>
</transition>
</template>
<template>
<location id="100" x="40" y="89"/>
<transition>
<source col="9"/>
</transition>
</template>
<system> system AND, OR;</system>
</nta>
Basically I want to merge the declaration and the system and the rest to be serial in the output xml file. How to do this using JAVA? Sorry for the long post!!!

In comparison with other available XML processing API, to me,
having DOMBuilder and SAXBuilder JDOM is better for:
Modifying the XML document
XML tree traversing and random access to any section
Merging documents
This is a complete working example for merging two XML document:
SAXBuilder builder = new SAXBuilder();
Document doc1 = builder.build(new File("E:\\XML1.xml"));
Document doc2 = builder.build(new File("E:\\XML2.xml"));
String rootName = doc1.getRootElement().getName();
Element newRoot = new Element(rootName);
Document newDoc = new Document(newRoot);
Element root1 = doc1.getRootElement();
Element root2 = doc2.getRootElement();
// creating declaraion element by merging the declaration content
Element declaration = new Element("declaration");
declaration.addContent(root1.getChildText("declaration"));
declaration.addContent(root2.getChildText("declaration"));
newRoot.addContent(declaration); // add declaration element to new document
newRoot.addContent(root1.getChild("template").clone());
// directly adding template from document XML1,
//after getting template child,
//it needs to be cloned to detached from its parent
newRoot.addContent(root2.getChild("template").clone());
// same for document XML2
/*** now code yourself for system element here ***/
XMLOutputter outputter = new XMLOutputter();
outputter.output(newDoc, System.out);
// output the new doc, pass your OutputStream to this function

You can use an xml parser such as dom to read the required parts (declaration and system) and later aggregate them to get your required out put.
you will get plenty of examples on reading and writing xml in java.

Parse XML as i write here or in any another way nad then use javax.xml.parsers.DocumentBuilder from here
to do what you want.Create a new XML doc.

Related

Dom4j - No such namespace prefix

I need to create an .xml file but compiller says to me:
No such namespace prefix
I want to get:
<root>
<header>
<etd:name>test</etd:name>
</header>
</root>
My code:
Document document = DocumentHelper.createDocument();
Element root = document.addElement("root", getXmlNamespace()).addAttribute(new QName("xmlns:etd"), "some-url-there");
Element header = root.addElement("header");
header.addElement("etd:name").addText("test");
I've tried with addElement(new QName("etd:name")) but that shows me empty value xmlns="" which i dont want.

Prevent JDOM2 from creating xmlns=""

I try to add new <class> elements to a persistence.xml file with JDOM2.
persistenceUnitEl.add(new Element("class").addContent(className));
The problem is that jdom2 always adds xmlns="" to the <class> elements.
How can i prevent this?
removeAttribute("xmlns") does not work and removeNameSpace(el.getNameSpace()) also does not work.
JDOM only adds the xmlns="" if you add child elements to other elements that are already in a namespace. The default Namespace in XML is the one which has no prefix. In the following example:
<root>
<child />
</root>
There are no namespace prefixes, and the default namespace is "".
The above XML snippet is semantically identical to:
<root xmlns="" >
<child />
</root>
The xmlns="" means that, any time you see an element that has no prefix, that you should put it in the 'empty' namespace "".
Now, if you want to put things in a namespace, and have a prefix, you would do:
<ns:root xmlns:ns="http://mynamespace">
<ns:child />
</ns:root>
Note that the root and child elements in the above example are in the namespace http://mynamespace, and that namespace has the prefix ns. The above code would be semantically identical to (has the same meaning as):
<root xmlns="http://mynamespace">
<child />
</root>
In the above example, the default namespace is changed from "" to be http://mynamespace, so now elements that have no prefix are in that default namespace http://mynamespace. To reiterate, the following two documents are identical:
<ns:root xmlns:ns="http://mynamespace">
<ns:child />
</ns:root>
and
<root xmlns="http://mynamespace">
<child />
</root>
Now, what does all of this have to do with your problem?
Well, your element persistenceUnitEl must be in a default namespace that is not "". Somewhere on that element, or on of it's parents, you have something like:
<tagname xmlns="...something....">
<PersistenceUnit>
</PersistenceUnit>
</tagname>
In the above, the PersistenceUnit is in the namespace ...something..... Now, you are asking JDOM to add the element new Element("class") to the document, so you are getting:
<tagname xmlns="...something....">
<PersistenceUnit>
<class xmlns="" />
</PersistenceUnit>
</tagname>
The reason is because you are telling JDOM to put it in the "" namespace (Namespace.NO_NAMESPACE). See the documentation for JDOM here: new Element(String name).
instead, what you want to do, is put it in the same namespace as the parent:
Namespace parentNamespace = persistenceUnitEl.getNamespace();
persistenceUnitEl.add(new Element("class", parentNamespace).addContent(className));
Now, the real question is whether the "class" element actually belongs in the same namespace as the parent, or not. But that is a question only you can answer.
Resources:
Namespace specification
Decent introduction
A tutorial (quite advanced)
JDOM's NamespaceAware documentation
JDOM's FAQ
From my understanding, I think this is what you want.
<RootTagname xmlns="...some namespace....">
<SubTag>
<NewElement yourAttrib="1"/>
</SubTag>
</RootTagname >
This is what you get.
<RootTagname xmlns="...some namespace....">
<SubTag>
<NewElement xmlns="" yourAttrib="1"/>
</SubTag>
</RootTagname >
Use the below snippet to create the new Element
Element newElement = new Element("NewElement", subElement.getNamespace());
Here is the full code.
Namespace namespace = Namespace.getNamespace("prefix", ".....some namespace....");
XPathBuilder<Element> subTagXpathelementBuilder = new XPathBuilder<Element>("//prefix:SubTag", Filters.element());
subTagXpathelementBuilder.setNamespace(namespace);
XPathFactory xpathFactory = XPathFactory.instance();
Document doc = (Document) builder.build(xmlFile);
XPathExpression<Element> xpath = subTagXpathelementBuilder .compileWith(xpathFactory);
List<Element> subElementsList = xpath.evaluate(doc);
for (Element subElement : subElementsList ) {
Element newElement = new Element("NewElement", subElement.getNamespace());
List<Attribute> newElementAttribList = newElement.getAttributes();
newElementAttribList .add(new Attribute("yourAttrib", "1"));
subElement .addContent(newElement);
}

What are best algorithms/patterns to read xml files using [java] sax?

Let's suppose we have the following xml
<books>
<book>
<id>...</id>
<title>...</title>
<references>
<book>
<id>...</id>
<title>...</title>
</book>
</references>
<authors>
<author>
<id>...</id>
<name>...</name>
<written-books>
<book>
<id>...</id>
<title>...</title>
</book>
</written-books>
</author>
</authors>
<book>
</books>
What I do now is to use booleans to find out in what sections we are (book,references,authors,written-books). I do this on starte/end element event ,After that on characters event I check
if (qName.equals("id"){
if (writtenBooks){
}else if (authors){
}else if (references){
}else{
}
}else if ("title")...
But it doesn't seem to be too elegant. Is there a better solution?
According to my understanding what you have to do is read the XML and then process it. (Check the existence of the elements etc.) You can use Apache Axiom to read xml files and get the content easily. Then you can process it as you want.I will put a example code segment to get the content of the xml file using AXIOM.
//read the xml file
StAXOMBuilder builder = new StAXOMBuilder(xmlStreamReader);
OMElement endPointElem = builder.getDocumentElement();
// go though the xml elemetns and do whatever you want
Iterator children = endPointElem.getChildElements();
while (children.hasNext()) {
........................
.......
}
For more details This post will helpful to you

creating a org.w3c.dom.Document object and appending it to a node

I have a xml file like this:
<?xml version="1.0" encoding="utf-8"?>
<Book>
<Author>
XYZ
</Author>
</Book>
I want to add a new node suppose Edition into this like:
<Book>
<Author>
XYZ
</Author>
<Edition>
5
</Edition>
</Book>
How can I do this using java?
I tried doing it as:
In a method I am passing the entire node and new node as a String but its throwing org.apache.xml.dtm.DTMDOMException when I did this:
Document doc = null;
doc = createEmptyDocument(true);
Element child = doc.createElement(childNodeName);
child.setNodeValue(childNodeValue);
node.appendChild(chid);//node is the main node which has all the elements
I'd recommend using something like DOM4J instead of the W3C classes. It adds a layer on top that makes manipulations easier.

Modify existing XML stylesheet processing instruction in Java

I'm reading an existing XML file and outputting it (using DOM).
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="test"?>
<Books>
<Book name="MyBook" />
</Books>
But how do I modify the XML stylesheet? -> href here set "test".
Something like this should work (untested)
Element root = doc.getDocumentElement();
XPath xpath = XPathFactory.newInstance().newXPath();
String expression = "/processing-instruction('xml-stylesheet')";
ProcessingInstruction pi;
pi = (ProcessingInstruction)xpath.evaluate(expression, doc, XPathConstants.NODE);
pi.setData("type='text/xsl' href='foo.xsl'");
Thats a bit tricky, but why not read the file first into a String and do a replace before sending it via a stream into the dom parser.

Categories