This is probably one of those easiest things to deal with but for some reason not working for me. I'm trying to add a new node after the root in dom tree.
Here's the original string:
<div class="discussionThread dt"><div class="dt_subject">2011 IS HERE!</div></div>
I'm trying to add a new node which is in the form of a string before . The final version should look like:
<div class="discussionThread dt"><div class="test">Test Val</div><div class="dt_subject">2011 IS HERE!</div></div>
As you can see, the new Test Val is being added immediately after the root div class. I've used few methods to place the node at the right place but its getting appended at the end.
Here's a sample which I referred from one of the earlier posts:
String newNode = "<div class="test">test</div>";
SAXReader reader = new SAXReader();
Document newNodeDocument = reader.read(new StringReader(newNode));
Document originalDoc = new SAXReader().read(new StringReader(content));
Element root = originalDoc.getRootElement();
Element givenNode = originalDoc.getRootElement();
givenNode.add(newNodeDocument.getRootElement());
This is resulting the node getting added at the end. I tried using insertBefore(), but didn't work out.
Any pointers will be highly appreciated.
Thanks
Why create a new Document or a new root Element? I think the shortest way is using Branch#content:
Returns the content nodes of this
branch as a backed List so that
the content of this branch may be
modified directly using the interface.
The List is backed by the Branch so
that changes to the list are reflected
in the branch and vice versa.
You just have to create the new Element and to add it to the root element through the List provided by content method (passing it the position index), this is my main:
public static void main(String[] args) throws DocumentException {
SAXReader reader = new SAXReader();
String xml = "<div class=\"discussionThread dt\"><div class=\"dt_subject\">2011 IS HERE!</div></div>";
Document document = reader.read(new StringReader(xml));
DefaultElement newElement = new DefaultElement("div");
newElement.addAttribute("class", "test");
newElement.add(new DefaultText("Test Val"));
List content = document.getRootElement().content();
if (content != null ) {
content.add(0, newElement);
}
System.out.println(document.asXML());
}
which prints out the following xml:
<div class="discussionThread dt"><div class="test">Test Val</div><div class="dt_subject">2011 IS HERE!</div></div>
In addition, you should also consider the use of xslt when you have to transform xml.
You're calling Element#add(Entity). From the Javadocs:
Adds the given Entity to this element. If the given node already has a parent defined then an IllegalAddException will be thrown.
So the new node you're adding will be added as a child of the node you're adding it to. You cannot add another node after the root node you have, because a document can have only one root node.
What you can do is create a new root node, then add the old root node and the new node as children of this new root node. Then set the root node of the document to the new root node.
Why not just create a new Document with the value you want, then append the other nodes to it?
Related
I need process a XML node as independent XML, add a new tag to the Node Document , update the original XML document with the new node info. Any help, advice or tutorial is welcome.
This is the original XML:
<ENVOLVENTE id="ENVOLVENTE">
<FirmaEmpresa>
<FirmaDonante>
<Firma>
<Relacion>
<RelacionId>32490342093249090234</RelacionId>
</Relacion>
<Formulario>
<Donante>
<DonanteNombre>Gloria Robles</DonanteNombre>
<DonanteCorreo>gloria#gmail.com</DonanteCorreo>
</Donante>
<Beneficiado>
<BeneficiarioPais>USA</BeneficiarioPais>
<BeneficiadoCorreo>usdonations#gmail.com</BeneficiadoCorreo>
</Beneficiado>
<Fabricantes>
<Fabricante>
<FabricanteNumeroOrden>1</FabricanteNumeroOrden>
<FabricantePais>MX</FabricantePais>
<FabricanteCorreo>fabricante#gmail.com</FabricanteCorreo>
</Fabricante>
</Fabricantes>
<ListaDonaciones>
<Donaciones>
<DonacionesNumeroOrden>1</DonacionesNumeroOrden>
<DonacionesProductoId>nombre</DonacionesProductoId>
<DonacionesCantidadDonada>100</DonacionesCantidadDonada>
<DonacionesFechaDonacion>2016-12-29T12:21:16</DonacionesFechaDonacion>
</Donaciones>
</ListaDonaciones>
</Formulario>
</Firma>
</FirmaDonante>
<Empresa>
<EmpresaPais>MX</EmpresaPais>
<EmpresaNombre>Donaciones A.C </EmpresaNombre>
<EmpresaDirecccion>AV. REFORMA 1900</EmpresaDirecccion>
<EmpresaCiudad>CDXM</EmpresaCiudad>
</Empresa>
<PermisoEmpresa>
<PermisoNumero>329023409324902349023409234</PermisoNumero>
</PermisoEmpresa>
</FirmaEmpresa>
</ENVOLVENTE>
Now, i need extract the node "FirmaDonante" to a new XML DOM:
<FirmaDonante>
<Firma>
<Relacion>
<RelacionId>32490342093249090234</RelacionId>
</Relacion>
<Formulario>
<Donante>
<DonanteNombre>Gloria Robles</DonanteNombre>
<DonanteCorreo>gloria#gmail.com</DonanteCorreo>
</Donante>
<Beneficiado>
<BeneficiarioPais>USA</BeneficiarioPais>
<BeneficiadoCorreo>usdonations#gmail.com</BeneficiadoCorreo>
</Beneficiado>
<Fabricantes>
<Fabricante>
<FabricanteNumeroOrden>1</FabricanteNumeroOrden>
<FabricantePais>MX</FabricantePais>
<FabricanteCorreo>fabricante#gmail.com</FabricanteCorreo>
</Fabricante>
</Fabricantes>
<ListaDonaciones>
<Donaciones>
<DonacionesNumeroOrden>1</DonacionesNumeroOrden>
<DonacionesProductoId>nombre</DonacionesProductoId>
<DonacionesCantidadDonada>100</DonacionesCantidadDonada>
<DonacionesFechaDonacion>2016-12-29T12:21:16</DonacionesFechaDonacion>
</Donaciones>
</ListaDonaciones>
</Formulario>
</Firma>
</FirmaDonante>
After that, I will modify the node as new XML document, something like that, with a new XML Element after the original Node.
<FirmaDonante>
<Firma>
<Relacion>
<RelacionId>32490342093249090234</RelacionId>
</Relacion>
<Formulario>
<Donante>
<DonanteNombre>Gloria Robles</DonanteNombre>
<DonanteCorreo>gloria#gmail.com</DonanteCorreo>
</Donante>
<Beneficiado>
<BeneficiarioPais>USA</BeneficiarioPais>
<BeneficiadoCorreo>usdonations#gmail.com</BeneficiadoCorreo>
</Beneficiado>
<Fabricantes>
<Fabricante>
<FabricanteNumeroOrden>1</FabricanteNumeroOrden>
<FabricantePais>MX</FabricantePais>
<FabricanteCorreo>fabricante#gmail.com</FabricanteCorreo>
</Fabricante>
</Fabricantes>
<ListaDonaciones>
<Donaciones>
<DonacionesNumeroOrden>1</DonacionesNumeroOrden>
<DonacionesProductoId>nombre</DonacionesProductoId>
<DonacionesCantidadDonada>100</DonacionesCantidadDonada>
<DonacionesFechaDonacion>2016-12-29T12:21:16</DonacionesFechaDonacion>
</Donaciones>
</ListaDonaciones>
</Formulario>
</Firma>
</FirmaDonante>
<Signature>
<SignedInfo/>
<KeyInfo/>
</Signature>
Finally, i need add the Node document in the same position in the original document, as Node, with the new tag:
<ENVOLVENTE id="ENVOLVENTE">
<FirmaEmpresa>
<FirmaDonante>
<Firma>
<Relacion>
<RelacionId>32490342093249090234</RelacionId>
</Relacion>
<Formulario>
<Donante>
<DonanteNombre>Gloria Robles</DonanteNombre>
<DonanteCorreo>gloria#gmail.com</DonanteCorreo>
</Donante>
<Beneficiado>
<BeneficiarioPais>USA</BeneficiarioPais>
<BeneficiadoCorreo>usdonations#gmail.com</BeneficiadoCorreo>
</Beneficiado>
<Fabricantes>
<Fabricante>
<FabricanteNumeroOrden>1</FabricanteNumeroOrden>
<FabricantePais>MX</FabricantePais>
<FabricanteCorreo>fabricante#gmail.com</FabricanteCorreo>
</Fabricante>
</Fabricantes>
<ListaDonaciones>
<Donaciones>
<DonacionesNumeroOrden>1</DonacionesNumeroOrden>
<DonacionesProductoId>nombre</DonacionesProductoId>
<DonacionesCantidadDonada>100</DonacionesCantidadDonada>
<DonacionesFechaDonacion>2016-12-29T12:21:16</DonacionesFechaDonacion>
</Donaciones>
</ListaDonaciones>
</Formulario>
</Firma>
</FirmaDonante>
<!--NEW TAG -->
<Signature>
<SignedInfo/>
<KeyInfo/>
</Signature>
<!--NEW TAG -->
<Empresa>
<EmpresaPais>MX</EmpresaPais>
<EmpresaNombre>Donaciones A.C </EmpresaNombre>
<EmpresaDirecccion>AV. REFORMA 1900</EmpresaDirecccion>
<EmpresaCiudad>CDXM</EmpresaCiudad>
</Empresa>
<PermisoEmpresa>
<PermisoNumero>329023409324902349023409234</PermisoNumero>
</PermisoEmpresa>
</FirmaEmpresa>
</ENVOLVENTE>
actually, i can extract the Node, but i have errors when i try to add a new Element the node document:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
DocumentBuilder builder = dbf.newDocumentBuilder();
InputStream stream = new ByteArrayInputStream(
xmlFile.getBytes(StandardCharsets.UTF_8));
Document document = builder.parse(stream);
Element elementFirmaDonante = (Element) document.getElementsByTagName("FirmaDonante").item(0);
DocumentBuilder documentBuilder = dbf.newDocumentBuilder();
Document documentoCODExporterMasEH = documentBuilder.newDocument();
Node newNode = documentoCODExporterMasEH.importNode(elementFirmaDonante, true);
documentoCODExporterMasEH.appendChild(newNode);
/*In this point all is OK, a can serialize de Document, but now, a can't add a new Item to the node document*/
/*
* This block, throws error:
* HIERARCHY_REQUEST_ERR: An attempt was made to insert a node where it is not permitted.
*/
Element anotherElement = (Element) document.getElementsByTagName("Empresa").item(0);
Node anotherNewNode = documentoCODExporterMasEH.importNode(anotherElement, true);
documentoCODExporterMasEH.insertBefore(anotherNewNode, newNode);
The above code is just to test that I can add new Elements or nodes to the DOM Object.
Any suggestions ??
Thanks in advance!!!!!
See the below code, I am able to insert a new node before Empresa node:-
Element anotherElement = (Element)document.getElementsByTagName("Empresa").item(0);
Element newTag = document.createElement("Signature");
Element childElem1=document.createElement("SignedInfo");
Element childElem2=document.createElement("KeyInfo");
newTag.appendChild(childElem1);newTag.appendChild(childElem2);
anotherElement.getParentNode().insertBefore(newTag, anotherElement);
Try to change your code like below:-
documentoCODExporterMasEH.insertBefore(newNode,anotherNewNode);
Essentially, i'm creating an XML document from a file (a database), and then i'm comparing another parsed XML file (with updated information) to the original database, then writing the new information into the database.
I'm using java's org.w3c.dom.
After lots of struggling, i decided to just create a new Document object and will write from there from the oldDocument and newDocument ones i'm comparing the elements in.
The XML doc is in the following format:
<Log>
<File name="something.c">
<Warning file="something.c" line="101" column="23"/>
<Warning file="something.c" line="505" column="71" />
</File>
</Log>
as an example.
How would i go about adding in a new "warning" Element to the "File" without getting the pesky "org.w3c.dom.DOMException: WRONG_DOCUMENT_ERR: A node is used in a different document than the one that created it." exception?
Cutting it down, I have something similar to:
public static Document update(Element databaseRoot, Element newRoot){
Document doc = db.newDocument(); // DocumentBuilder defined previously
Element baseRoot = doc.createElement("Log");
//for each file i have:
Element newFileRoot = doc.createElement("File");
//some for loop that parses through each 'file' and looks at the warnings
//when i come to a new warning to add to the Document:
NodeList newWarnings = newFileToCompare.getChildNodes(); //newFileToCompare comes from the newRoot element
for (int m = 0; m < newWarnings.getLength(); m++){
if(newWarnings.item(m).getNodeType() == Node.ELEMENT_NODE){
Element newWarning = (Element)newWarnings.item(m);
Element newWarningRoot = (Element)newWarning.cloneNode(false);
newFileRoot.appendChild(doc.importNode(newWarningRoot,true)); // this is what crashes
}
}
// for new files i have this which works:
newFileRoot = (Element)newFiles.item(i).cloneNode(true);
baseRoot.appendChild(doc.importNode(newFileRoot,true));
doc.appendChild(baseRoot);
return doc;
}
Any ideas? I'm beating my head against the wall. First time doing this.
Going through with a debugger I verified that the document owners were correct. Using node.getOwnerDocument(), I realized that the newFileRoot was connected to the wrong document earlier when I created it, so I changed
Element newFileRoot = (Element)pastFileToFind.cloneNode(false);
to
Element newFileRoot = (Element)doc.importNode(pastFileToFind.cloneNode(false),true);
since later on when i was trying to add the newWarningRoot to newFileRoot, they had different Documents (newWarningRoot was correct but newFileRoot was connected to the wrong document)
I need to build a tree view of the elements present in an XML file.
For example,
<abc>
<abcd/>
<abcd/>
</abc>
<def>
<defg/>
<jkl/>
<defg/>
</def>
My TreeView should look like this:
>abc
>abcd
>abcd
>def
>defg
>jkl
>defg
>def
I need to read the elements and build a treeView in JavaFX. I'm not sure which data structure to use here. If I use List> to store <(node, children)>, each child can have multiple children and they can have many and so on. So, I'm not able to figure out what data structure to use. Can anyone suggest what is the possible way here?
UPDATE:
Using the reference in this Java: How to display an XML file in a JTree , I tried doing like this in JavaFX.
public TreeView<String> build(String pathToXml) throws Exception {
SAXReader reader = new SAXReader();
Document doc = (Document) reader.read(pathToXml);
return new TreeView<String>(build(doc.getRootElement()));
}
public TreeItem<String> build(Element e) {
TreeItem<String> item = new TreeItem<String>(e.getText());
for(Object o : e.elements()) {
Element child = (Element) o;
item.getChildren().add(build(child));
}
return item;
}
But I'm not able to see the content in TreeView. When I debugged, e.getText() is having only "\n\n". Is there a way to handle it? Am I doing this correctly?
charactersI am trying to include the correct characters in an XML document text node:
Element request = doc.createElement("requestnode");
request.appendChild(doc.createTextNode(xml));
rootElement.appendChild(request);
The xml string is a segment of a large xml file which I have read in:
Document doc = docBuilder.newDocument();
Element rootElement = doc.createElement("rootnode");
doc.appendChild(rootElement);
<firstname>John</firstname>
<dateOfBirth>28091999</dateOfBirth>
<surname>Doe</surname>
The problem is that passing this into createTextNode is replacing some of the charters:
<firstname>John</firstname>
<dateOfBirth>28091999</dateOfBirth>
<surname>Doe</surname>
Is there any way I can keep the correct characters (< , >) in the textnode. I have read about using importnode but this is not correctly XML, only a segment of a file.
Any help would be greatly appreciated.
EDIT: I need the xml string (which is not fully formatted xml, only a segment of an external xml file) to be in the "request node" as I am building XML to be imported into SOAP UI
You can't pass the element tag and text to the createTextNode() method. You only need to pass the text. You need then to append this text node to an element.
If the source is another XML document, you must extract the text node from an element and insert it in to the other. You can grab a Node (element and text) and try to inserted as a text node in the other. That is why you are seeing all the escape characters.
On the other hand, you can insert this Node into the other XML (if the structure is allowed) and it should be just fine.
In your context, I assume "request" is some sort of Node. The child element of a Node could be another element, text, etc. You have to be very specific.
You can do something like:
Element name = doc.createElement("name");
Element dob = doc.createElement("dateOfBirth");
Element surname = doc.createElement("surname");
name.appendChild( doc.createTextNode("John") );
dob.appendChild( doc.createTextNode("28091999") );
surname.appendChild( doc.createTextNode("Doe") );
Then you can add these element to a parent node:
node.appendChild(name);
node.appendChild(dob);
node.appendChild(surname);
UPDATE: As an alternative, you can open a stream to a document and insert your XML string as a byte stream. Something like this (untested code, but close):
String xmlString = "<firstname>John</firstname><dateOfBirth>28091999</dateOfBirth><surname>Doe</surname>";
DocumentBuilderFactory fac = javax.xml.parsers.DocumentBuilderFactory.newInstance();
DocumentBuilder builder = fac.newDocumentBuilder();
Document newDoc = builder.parse(new ByteArrayInputStream(xmlString.getBytes()));
Element newElem = doc.createElement("whatever");
doc.appendChild(newElem);
Node node = doc.importNode(newDoc.getDocumentElement(), true);
newElem.appendChild(node);
Something like that should do the trick.
Example-
<Envision>
<Employee>
<Employee-code>Shiva kumar</Employee-code>
<Employee-Name>474</Employee-Name>
</Employee>
<Employee>
<Employee-code>Santhosh Kumar</Employee-code>
<Employee-Name>475</Employee-Name>
</Employee>
</Envision>
I want to create an xml file as shown above xml.But i am able to do only this -
<Employee>
<Employee-code>Shiva kumar</Employee-code>
<Employee-name>474</Employee-name>
<Employee>
</Envision>
by following code-
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
DocumentBuilder builder=factory.newDocumentBuilder();
Document doc=builder.newDocument();
Element root=doc.createElement("Envision");
doc.appendChild(root);
Element ele=doc.createElement("Employee_Name");
ele.appendChild(doc.createTextNode("Shiva Kumar"));
root.appendChild(ele);
ele=doc.createElement("Employee_Code");
ele.appendChild(doc.createTextNode("474"));
root.appendChild(ele);
TransformerFactory transformerFactory =TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(System.out);
transformer.transform(source, result);
Whenever i want to add second block to that code by appending this below code to above code
after the employee code tag
Element root1=doc.createElement("Envision");
doc.appendChild(root1);
ele=doc.createElement("Employee_Name");
ele.appendChild(doc.createTextNode("Vijay Babu"));
root1.appendChild(ele);
ele=doc.createElement("Employee_Code");
ele.appendChild(doc.createTextNode(""));
root1.appendChild(ele);
Then i am gettting an Error message like "Creation of the node is not permitted".Please help me in this case
You can't create a second root element - that's simply invalid in XML. But you don't need to. All you need to do is reuse your existing root element. Look at the XML at the top of the question - it only has a single root element, with two Employee elements, right?
It's not clear why you're not creating Employee elements, by the way. You're currently creating Employee_Name and Employee_Code directly under Envision, which doesn't match your sample XML.
I would suggest extracting out the employee-adding code like this:
private static void addEmployee(Document doc, String name, String code) {
Element employee = doc.createElement("Employee");
doc.getDocumentElement().appendChild(employee);
Element nameElement = doc.createElement("Employee_Name");
nameElement.appendChild(doc.createTextNode(name));
employee.appendChild(nameElement);
Element codeElement = doc.createElement("Employee_Code");
codeElement.appendChild(doc.createTextNode(name));
employee.appendChild(codeElement);
}
Then:
Document doc = builder.newDocument();
Element root = doc.createElement("Envision");
doc.appendChild(root);
addEmployee(doc, "Shiva Kumar", "474");
addEmployee(doc, "Vijay Babu", "");
(Alternatively, you could change addEmployee to take the element to append it to.)
XML file can have only one root element. Therefore if you really need more Envision nodes then create one root node for them e.g. ENVISIONS
<ENVISIONS>
<ENVISION>
...
<ENVISION>
<ENVISION>
...
<ENVISION>
</ENVISIONS>
Haven't you forgotten to create EMPLYEE node, have you?
Once you create the root element, you can't create and append another root element to the document.
doc.appendChild(root);
If you want to get that root element to append another employee element to it later you can call the doc.getDocumentElement()
Element root1=doc.getDocumentElement()