Appending child element from other document - java

In my program i have to create some document creator and I want to split functionality of creating elements into several classes. Each class will create a single element and main creator will extract that element via interface and attach to body.
The thing is that i don't want to pass any arguments into constructors call e.g.
creator.createDocument()
.setDocumentHeader(
new DocumentHeader()
.setSomeValue(41)
)
To simplify the problem lets say that I have a code
import org.w3c.dom.Document;
import org.w3c.dom.Element;
DocumentBuilderFactory dbfac1 = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder1 = dbfac1.newDocumentBuilder();
Document document1 = docBuilder1.newDocument();
DocumentBuilderFactory dbfac2 = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder2 = dbfac2.newDocumentBuilder();
Document document2 = docBuilder2.newDocument();
Element elementFromDoc1 = document1.createElement("body");
Element elementFromDoc2 = document2.createElement("someElement");
The question is, is that legal to do the following operation?
elementFromDoc1.appendChild(elementFromDoc2);

The code you have will throw an exception about the element being from a different document.
However, you can use document1.importNode I think. Here is the documentation:
http://docs.oracle.com/javase/7/docs/api/org/w3c/dom/Document.html#importNode(org.w3c.dom.Node,%20boolean)
And here is an example from another question:
Java appending XML docs to existing docs

Related

Special characters creates problem while writing xml

first of all please excuse my shallow understanding into coding as I am a business analyst. Now my question. I am writing java code to convert a csv into xml. I am able to read csv successfully into objects. However, while writing the xml, when special a space or "=" is encounteredan error is thrown.
Piece of the problematic code, I have imporovised the value in create element just to highlight the problem. In actual I am getting this value from an object:-
DocumentBuilderFactory documentFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentFactory.newDocumentBuilder();
Document xmlDocument= documentBuilder.newDocument();
Element root = xmlDocument.createElement("Media NationalGroupId="8" AllFTA="1002" AllSTV="1001");
xmlDocument.appendChild(root);
My xml should look something like this
<Media DateCreated="20200224 145251" NationalGroupId="8" AllFTA="1002" AllSTV="1001" AllTV="1000" NextId="1000000">
createElement should only receive Media as the argument.
To add the other attributes (DateCreated, NationalGroupId, etc), you need to call setAttribute on root, one by one.

Comparing two xml files and get the differences

I am trying to compare two XML files. My requirement is to compare old and new xml files and if any difference is there merge it into the new xml file.
Below code snippet gives me whether both files are equal or not.
public static void compare() throws SAXException, IOException, ParserConfigurationException{
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
dbf.setCoalescing(true);
dbf.setIgnoringElementContentWhitespace(true);
dbf.setIgnoringComments(true);
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc1 = db.parse(new File("old.xml"));
doc1.normalizeDocument();
Document doc2 = db.parse(new File("new.xml"));
doc2.normalizeDocument();
System.out.println (doc1.isEqualNode(doc2));
}
But I want the differences also. Please tell me how I can get the differences.
I have already tried XMLUnit , but I dont want to use it.
You can use jaxb to parse your xml and contruct java objects with unmarshall method and compare your generated objects.
See it here : How to compare jaxb, object, string to find differences
You can also use google diff-match-patch api to compare your two xml as Strings and patch to create the new.
https://code.google.com/archive/p/google-diff-match-patch/
Diff demo : https://neil.fraser.name/software/diff_match_patch/svn/trunk/demos/demo_diff.html
Patch Demo : https://neil.fraser.name/software/diff_match_patch/svn/trunk/demos/demo_patch.html
Sources are available on github : https://github.com/GerHobbelt/google-diff-match-patch

Error while creating a Document variable with a XML parser in Java

lately i've been gettin an error while running my code
I'm using this code to create the Document file
DocumentBuilderFactory bFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = bFactory.newDocumentBuilder();
Document doc = (Document) dBuilder.parse(xmlfile);
And i'm getting this error
Exception in thread "main" java.lang.ClassCastException:
com.sun.org.apache.xerces.internal.dom.DeferredDocumentImpl cannot be
cast to javax.swing.text.Document at rss.RSS.main(RSS.java:72)
C:\Users\user\AppData\Local\NetBeans\Cache\8.2\executor-snippets\run.xml:53:
Java returned: 1
BUILD FAILED (total time: 0 seconds)
I'm not very familiar with programming but i've got a task to do. I would be glad if you could help
It appears that the import being used for the following line is javax.swing.text.Document:
Document doc = (Document) dBuilder.parse(xmlfile);
One possible explanation is that your source file is using both of the following two classes:
javax.swing.text.Document
org.w3c.dom.Document
This explanation would make sense if you are trying to do both Swing and XML dom stuff in the same source file. A workaround is to use the fully qualified class name here, e.g.
org.w3c.dom.Document doc = (org.w3c.dom.Document) dBuilder.parse(xmlfile);
Note that you could also make org.w3c.dom.Document the primary import and then use javax.swing.text.Document everywhere for the Swing document class. In practice, you would probably want to be consistent everywhere, i.e. use fully qualified for all Swing or for all org.w3c.dom classes. And which class is used to most might be what you choose to import, which would free you from having to type package names the most.
Looks like you are importing class from wrong package than what you need for XML parsing, please refer the below code for importing class from right package.
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import org.w3c.dom.Document;
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = (Document) dBuilder.parse(xmlfile);

Mockito: How to mock XML Document object to retrieve value from XPath

I am trying to mock a org.w3c.dom.Document object such that calling XPath.evaluate() should return a defined value, e.g., foo, as below:
Document doc = Mockito.mock(Document.class);
Mockito.when(XPathUtils.xpath.evaluate("/MyNode/text()", doc, XPathConstants.STRING)).thenReturn("foo");
I shall pass the doc object to the target method that will extract the textual contents of node MyNode as foo.
I have tried mocking nodes and setting in the doc object as follows:
Node nodeMock = mock(Node.class);
NodeList list = Mockito.mock(NodeList.class);
Element element = Mockito.mock(Element.class);
Mockito.when(list.getLength()).thenReturn(1);
Mockito.when(list.item(0)).thenReturn(nodeMock);
Mockito.when(doc.getNodeType()).thenReturn(Node.DOCUMENT_NODE);
Mockito.when(element.getNodeType()).thenReturn(Node.ELEMENT_NODE);
Mockito.when(nodeMock.getNodeType()).thenReturn(Node.TEXT_NODE);
Mockito.when(doc.hasChildNodes()).thenReturn(false);
Mockito.when(element.hasChildNodes()).thenReturn(true);
Mockito.when(nodeMock.hasChildNodes()).thenReturn(false);
Mockito.when(nodeMock.getNodeName()).thenReturn("MyNode");
Mockito.when(nodeMock.getTextContent()).thenReturn("MyValue");
Mockito.when(element.getChildNodes()).thenReturn(list);
Mockito.when(doc.getDocumentElement()).thenReturn(element);
But this is giving error like:
org.mockito.exceptions.misusing.WrongTypeOfReturnValue: String cannot
be returned by hasChildNodes() hasChildNodes() should return boolean
Is my approach correct and I am missing just another mock, or should I approach it differently? Please help.
Don't mock types you don't own !, it's wrong.
To avoid repeating here's an answer that explains why https://stackoverflow.com/a/28698223/48136
EDIT : What I mean is that the code should have usable builder methods (either in the production or in the test classpath) that should be able to create a real Document whatever the source of that document, but certainly not a mock.
For exemple this factory method or builder could use the DocumentBuilder this way :
class FakeXMLBuilder {
static Document fromString(String xml) {
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
return dBuilder.parse(new ByteArrayInputStream(xml.getBytes("UTF_8")));
}
}
Of course this has to be tailored to the need of the project, and this can be customized a lot more. In my current project we have a lot of test builders that can create objects, json, etc. For exemple :
Leg leg = legWithRandomId().contact("Bob").duration(234, SECONDS).build();
String leg = legWithRandomId().contact("Bob").duration(234, SECONDS).toJSON();
String leg = legWithRandomId().contact("Bob").duration(234, SECONDS).toXML();
Whatever leg = legWithRandomId().contact("Bob").duration(234, SECONDS).to(WhateverFactory.whateverFactory());
Use Jsoup.parse() with a test XML String. Something like the following should work, for testing some instance method I've assumed is testClassInstance.readFromConnection(String url):
// Turn a block of XML (static String or one read from a file) into a Document
Document document = Jsoup.parse(articleXml);
// Tell Mockito what to do with the Document
Mockito.when(testClassInstance.readFromConnection(Mockito.any()))
.thenReturn(document);
I'm used to referring to this as "mocking" a Document, but it's just creating and using a real Document, which is then used in mocking other methods. You can construct the xml version of document however you like, or use its regular setters to manipulate it for testing whatever your code is supposed to do with the file. You could also replace that mess of reading-the-file with a constant string, provided it's short enough to be manageable.

create simple xml in Java

I am trying to build server that sends a xml file to client. I am getting info from db and wants to build from that xml file.
But I have a problem with:
DocumentBuilder documentBuilder = null;
Document doc =documentBuilder.newDocument();
I am getting NullPointerException. Here is me full code:
public void createXmlTree() throws Exception {
//This method creates an element node
DocumentBuilder documentBuilder = null;
Document doc =documentBuilder.newDocument();
Element root = doc.createElement("items");
//adding a node after the last child node of the specified node.
doc.appendChild(root);
for(int i=0;i<db.stories.size();i++){
Element child = doc.createElement("item");
root.appendChild(child);
Element child1 = doc.createElement("title");
child.appendChild(child1);
Text text = doc.createTextNode(db.stories.get(i).title);
child1.appendChild(text);
//Comment comment = doc.createComment("Employee in roseindia");
//child.appendChild(comment);
Element child2 = doc.createElement("date");
child.appendChild(child2);
Text text2 = doc.createTextNode(db.stories.get(i).date);
child2.appendChild(text2);
Element child3 = doc.createElement("text");
child.appendChild(child3);
Text text3 = doc.createTextNode(db.stories.get(i).text);
child3.appendChild(text3);
root.appendChild(child3);
Well yes, you would get a NullPointerException. You're calling a method on a null reference - very clearly, given that you've assigned the documentBuilder a null value on the line before. You need to get an instance of DocumentBuilder to start with. For example:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = factory.newDocumentBuilder();
of course you are getting a NullPointerException, your DocumentBuilder is null.
Try instantiating it first.
// Step 1: create a DocumentBuilderFactory
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
// Step 2: create a DocumentBuilder
DocumentBuilder db = dbf.newDocumentBuilder();
Guys are right about DocumentBuilder. But may I offer you other solution? Your servlet mostly deals with generating of XML itself, i.e. produces kind of markup. This is the purpose of JSP. You can implement simple JSP page that will actually contain template of your XML and some code that inserts dynamic data. This is much simpler and easier to maintain.
Yes, JSP typically generate HTML but no-one said that they cannot generate XML or any other text format. Just do not forget to set content type to text/xml.
Do you really need to write you XML manually?
Do you have the XSD of the XML you want to write?
Because, it would be easier to generate some classes using XJC/JAXB and use the marshaller to write your XML file.

Categories