xml node deletion not working properly in java using dom parser? - java

Here i have xml node where i'm displaying and selecting particular node to delete.For my below xml file and code ,only first node is deleting though i select second node.
<root>
<book> <!--node 1 -->
<id>1111</id>
<name>abacd</name>
<author>abcd</author>
<price>700</price>
<category>abcd</category>
</book>
<book> <!--node 2 -->
<id>2222</id>
<name>abacd</name>
<author>abcd</author>
<price>700</price>
<category>abcd</category>
</book>
<book> <!--node 3 -->
<id>3333</id>
<name>abacd</name>
<author>abcd</author>
<price>700</price>
<category>abcd</category>
</book>
</root>
and my java code to delete node as
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(fXmlFile);
int nodeValue = Integer.parseInt(nodeNumber);
//nodeValue is node number eg: 2;
NodeList bookList = doc.getElementsByTagName("book");
for (int i = 1; i <= bookList.getLength(); i++) {
if (i == nodeValue) {
Element rootElement = (Element) doc.getElementsByTagName("book").item(0);
Element idElement = (Element) doc.getElementsByTagName("id").item(0);
idElement.getParentNode().removeChild(idElement);
Element nameElement = (Element) doc.getElementsByTagName("name").item(0);
nameElement.getParentNode().removeChild(nameElement);
Element authorElement = (Element) doc.getElementsByTagName("author").item(0);
authorElement.getParentNode().removeChild(authorElement);
Element priceElement = (Element) doc.getElementsByTagName("price").item(0);
priceElement.getParentNode().removeChild(priceElement);
Element categoryElement = (Element) doc.getElementsByTagName("category").item(0);
categoryElement.getParentNode().removeChild(categoryElement);
rootElement.getParentNode().removeChild(rootElement);
doc.normalize();
}
}
could anybody guide me where to change my code.

You always call the first node by this
doc.getElementsByTagName("book").item(0);
Instead try to use
doc.getElementsByTagName("book").item(nodeValue);
Or use bookList.item(nodeValue) to access the node directly

if we want to delete node according to node number then below code helps.I got my answer by this
int nodeValue = Integer.parseInt(nodeNumber);
NodeList bookList = doc.getElementsByTagName("book");
Node nNode = bookList.item(nodeValue);
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element eElement = (Element) nNode;
eElement.getParentNode().removeChild(nNode);
}
It will delete selected node (eg:2).

Related

Tag names are missing in the XML parsed except the root element

I am reading a dynamic XML file (without any known structure) and putting the relevant tag name and value to a hashmap (ex: metadata<tagName, Value> ).
My issue here is, I can not get the tagName but it only adds the root tagName and all the values of entire xml.
my XML is:
<?xml version="1.0" encoding="UTF-8"?>
<form kwf="VARA">
<sec1>
<docID>2d2c5bf209b79d8b1a1f840ce4ce4030e66a76d6</docID>
<qrCode>xx.jpg</qrCode>
<title>NOOO FORM NAME</title>
<ELO_VARAFNAME>NO</ELO_VARAFNAME>
<ELO_VARALNAME>NAME</ELO_VARALNAME>
<ELO_VARAEMAIL>noname#gmail.com</ELO_VARAEMAIL>
<ELO_VARAORBEONDOCID>2d2c5bf209b79d8b1a1f840ce4ce4030e66a76d6</ELO_VARAORBEONDOCID>
</sec1>
</form>
My Code is:
public static Map<String,String> getMetaDataFromOrbeonXML(File fXmlFile) throws SAXException, ParserConfigurationException, IOException
{
Map metaData = new HashMap();
String formName="";
String docID = "";
try {
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(fXmlFile);
doc.getDocumentElement().normalize();
System.out.println("Root element :" + doc.getDocumentElement().getNodeName());
NodeList nList = doc.getElementsByTagName("form");
for (int temp = 0; temp < nList.getLength(); temp++) {
Node nNode = nList.item(temp);
System.out.println("\nCurrent Element :" + nNode.getNodeName());
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element eElement = (Element) nNode;
docID = eElement.getElementsByTagName("docID").item(0).getTextContent();
metaData.put("docID", docID);
metaData.put("appName", APP_NAME);
metaData.put(eElement.getTagName(), eElement.getTextContent());
System.out.println("META DATA MAP: "+ metaData.toString());
}
}
} catch (Exception e) {
e.printStackTrace();
}
return metaData;
}
And the out put is:
{form= 2d2c5bf209b79d8b1a1f840ce4ce4030e66a76d6
xx.jpg
NOOO FORM NAME
NO
NAME
noname#gmail.com
2d2c5bf209b79d8b1a1f840ce4ce4030e66a76d6
, docID=2d2c5bf209b79d8b1a1f840ce4ce4030e66a76d6, appName=VIRGINAUSI, formName=AITSLForm}
Tag names are missing in the map except the root element. Please help !
The code above correctly adds 2 entries in the map. The first entry, maps element Form to it's text content (which is the collection of the text content of all it's descendant nodes).
If you want to access the descendant nodes you'll need to use eElement.getChildNodes() and iterate over the NodeList returned.
This might be useful:
Java: Most efficient method to iterate over all elements in a org.w3c.dom.Document?

Parse XML node by node and check for leaf node

I used XPath expression //*[count(./*) = 0] to find the leaf nodes in an XML. But instead of using the expression, I wanted to parse the XML, node by node and check if it is a leaf node or not. How can I accomplish this? My XML is a dynamic one.
Using the following java code you can parse the xml and use docEle.hasChildNodes() to check it a leaf node or not.
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document dom = db.parse("file.xml");
Element docEle = dom.getDocumentElement();
NodeList nl = docEle.getChildNodes();
if (nl != null && nl.getLength() > 0) {
for (int i = 0; i < nl.getLength(); i++) {
if (nl.item(i).getNodeType() == Node.ELEMENT_NODE) {
Element el = (Element) nl.item(i);
el.getTextContent().trim();
}
}
}
}

Java XML with namespace issue

I have this code:
org.w3c.dom.Document doc = docBuilder.parse(representation.getStream());
Element element = doc.getDocumentElement();
NodeList nodeList = element.getElementsByTagName("xnat:MRSession.scan.file");
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
// do something with the current element
my problem is with getElementsByTagName("xnat:MRSession.scan.file")
my xml looks like this:
<?xml version="1.0" encoding="UTF-8"?><xnat:MRSession "REMOVED DATA IGNORE">
<xnat:sharing>
<xnat:share label="23_MR1" project="BOGUS_GSU">
<!--hidden_fields[xnat_experimentData_share_id="1",sharing_share_xnat_experimentDa_id="xnat_E00001"]-->
</xnat:share>
</xnat:sharing>
<xnat:fields>
<xnat:field name="studyComments">
<!--hidden_fields[xnat_experimentData_field_id="1",fields_field_xnat_experimentDat_id="xnat_E00001"]-->S</xnat:field>
</xnat:fields>
<xnat:subject_ID>xnat_S00002</xnat:subject_ID>
<xnat:scanner manufacturer="GE MEDICAL SYSTEMS" model="GENESIS_SIGNA"/>
<xnat:prearchivePath>/home/ryan/xnat_data/prearchive/BOGUS_OUA/20120717_131900137/23_MR1</xnat:prearchivePath>
<xnat:scans>
<xnat:scan ID="1" UID="1.2.840.113654.2.45.2.108830" type="SAG LOCALIZER" xsi:type="xnat:mrScanData">
<!--hidden_fields[xnat_imageScanData_id="1"]-->
<xnat:image_session_ID>xnat_E00001</xnat:image_session_ID>
<xnat:quality>usable</xnat:quality>
<xnat:series_description>SAG LOCALIZER</xnat:series_description>
<xnat:scanner manufacturer="GE MEDICAL SYSTEMS" model="GENESIS_SIGNA"/>
<xnat:frames>29</xnat:frames>
<xnat:file URI="/home/ryan/xnat_data/archive/BOGUS_OUA/arc001/23_MR1/SCANS/1/DICOM/scan_1_catalog.xml" content="RAW" file_count="29" file_size="3968052" format="DICOM" label="DICOM" xsi:type="xnat:resourceCatalog">
So Basically I need to be able to iterate through all the xnat:MRSession/xnat:scan/xnat:file
elements and make some changes. Problem is
getElementsByTagName("xnat:MRSession.scan.file")
Is always null. Please help. Thanks
You could try the following using XPath:
Document document = // the parsed document
XPathFactory xPathFactory = XPathFactory.newInstance();
NodeList allFileNodes = xPathFactory.newXPath().evaluate("\\XNAT_NAMESPACE:file", document.getDocumentElement(), XPathConstants.NODESET);
Instead XNAT_NAMESPACE you would need to specify the exact namespace that is meant with the prefix "xnat" in your example.

Child elements of DOM

I have this XML file:
<scene>
<texture file="file1.dds"/>
<texture file="file2.dds"/>
...
<node name="cube">
<texture name="stone" unit="0" sampler="anisotropic"/>
</node>
</scene>
I need all child element of 'scene' that are named "texture", but with this code:
Element rootNode = document.getDocumentElement();
NodeList childNodes = rootNode.getElementsByTagName("texture");
for (int nodeIx = 0; nodeIx < childNodes.getLength(); nodeIx++) {
Node node = childNodes.item(nodeIx);
if (node.getNodeType() == Node.ELEMENT_NODE) {
// cool stuff here
}
}
i also get the 'texture' elements which are inside 'node'.
How can i filter these out? Or how can i get only the elements that are direct childs of 'scene'?
You can do it using Xpath, consider the following example taken from the JAXP Specification 1.4 (which I recommend you to consult for this):
// parse the XML as a W3C Document
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
org.w3c.Document document = builder.parse(new File("/widgets.xml"));
// evaluate the XPath expression against the Document
XPath xpath = XPathFactory.newInstance().newXPath();
String expression = "/widgets/widget[#name='a']/#quantity";
Double quantity = (Double) xpath.evaluate(expression, document, XPathConstants.NUMBER);
I found myself a solution that works fine:
Element parent = ... ;
String childName = "texture";
NodeList childs = parent.getChildNodes();
for (int nodeIx = 0; nodeIx < childs.getLength(); nodeIx++) {
Node node = childs.item(nodeIx);
if (node.getNodeType() == Node.ELEMENT_NODE
&& node.getNodeName().equals(name)) {
// cool stuff here
}
}

How to navigate dom tree from XML in java

Below is a sample of the xml I am using, I have striped out some of the fields as they are unnecessary to demonstrate my point.
I am trying to parse the orders from this xml. However, I encounter a problem when I try to parse the product sets for each order. When the first order is processing, instead of adding the 2 sets detailed below, it will add all the sets it can find in the xml into the first order. I am not sure how to get around this as this is all quite new to me. Below is my java...
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(xmlFile);
doc.getDocumentElement().normalize();
// Create a list of orders and sub elements
System.out.println("Root element :" + doc.getDocumentElement().getNodeName());
nList = doc.getElementsByTagName("order");
setList = doc.getElementsByTagName("set");
orders = new Order[nList.getLength()];
Node nNode = nList.item(i);
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element eElement = (Element) nNode;
temp = new Order();
// Populate order with details from XML
parseClientDetails(eElement);
// Add sets
parseSets();
temp.setSets(setArray);
orders[i] = temp;
}
...
private void parseSets() {
Node nNode;
Element element;
for (int c = 0; c < setList.getLength(); c++) {
nNode = setList.item(c);
element = (Element) nNode;
tempSet = new Set();
tempSet.setBandwidth(getValue("bandwidth", element));
tempSet.setCategory(getValue("category", element));
tempSet.setSet_package(getValue("package", element));
setArray.add(tempSet);
}
}
XML:
<orderSet>
<order>
<customer name="SelectCustomerDetails">
<clientId>UK12345</clientId>
<etc>...</etc>
</customer>
<product>
<set>
<category>Silver</category>
<package>3000IP</package>
<bandwidth>160</bandwidth>
</set>
<set>
<category>Silver</category>
<package>3000IP</package>
<bandwidth>320</bandwidth>
</set>
</product>
</order>
<order>
...
</order>
</orderSet>
The problem is that you are calling doc.getElementsByTagName("set") which gives you a list of all sets in the entire document. Instead, you need to call it on each order, like this:
nList = doc.getElementsByTagName("order");
orders = new Order[nList.getLength()];
Node nNode = nList.item(i);
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element eElement = (Element) nNode;
//get the sets for the current order only
NodeList setList = eElement.getElementsByTagName("set");
//now process the sets
}
You can use the 'javax.xml.xpath' APIs to get the content you need from the XML document. These APIs were introduced in Java SE 5 and provide much more control than 'getElementsByTagName'.
Example
What is best way to change one value in XML files in Java?

Categories

Resources