2

I have this string containing my request xml. I want to delete below "id" tags from this string if they exist and return it back. Removing "Identity" completely will also work, if that can be done.

To be deleted :
 <Identity>
<id extension="7865232" aan = "BUH"/>
<code/>
</Identity>
<Identity>
<id extension="88769032" aan = "DIH"/>
<code/>
</Identity>

String XMLString= "<request version ="1.0">
<minMatch>
<val>100</val>
</minMatch>
<paramList>
<payLoad display = "Full" type="F">
</payLoad>
<IQC code = "2">
</IQC>
<Control display="Default" type = "D">
</Control>
<member>
<memCode code = "Active"
</memCode>
<id extension="12345" aan="ACC"></id>
<id extension="54321" aan="REQ"></id>
<id extension="554376" aan="PDR"></id>
<id extension="66321" aan="NJQ"></id>
<addr use = "H">
<streetLine>123</streetLine>
<city>POLIS</city>
<state>NY</state>
<postalCode>44321</postalCode>
</addr>
<telecom value = "5543213">
</telecom>
<Person>
<name>
<given>JOHN</given>
<family>BILL</family>
</name>
<GenderCode code ="M" display="Male">
</GenderCode>
<birthime vaue="19651002">
</birthime>
<Identity>
<id extensio="7865232" aan = "BUH"/>
<code/>
</Identity>
<Identity>
<id extensio="88769032" aan = "DIH"/>
<code/>
</Identity>
</Person>
</member>
----
---
</request>"

I am using below code to achieve the same but it's not working and giving me The constructor DOMSource(Document) is undefined. I tired converting document into a byte Array but that's also not working.Is there any way i can simply do this in Java 1.8. Any other approach is also welcome. Please suggest.Thank you!

public void removeIds(String xmlString){

Document doc = null;
SAXBuilder saxbuilder = new SAXBuilder();

try{
doc = saxbuilder.build(new StringReader(xmlString));
}catch(JDOMException je){
je.printStackTrace();
}catch(IOException ie){
ie.printStackTrace();
}

Element rootNode = doc.getRootElement();
IteratorIterable<Element> rootChildren=rootNode.getDescendants(new ElementFilter("Person"));

for(Element Person:rootChildren){
 for(Element Identity:Person.getChildren("Identity")){

((Element) doc.getRootElement.getDescendants(new ElementFilter("Identity"))).removeChild("id");

  }
}

try{

TransformerFactory tf = TransformerFactory.newInstance();
        Transformer transformer;
        
            transformer = tf.newTransformer();

            // transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");

            StringWriter writer = new StringWriter();
            transformer.transform(new DOMSource(doc), new StreamResult(writer));
            String output = writer.getBuffer().toString();
            return output;
        } catch (TransformerException e) {
            e.printStackTrace();
        }
        
       
    }
1
  • Anyone who could help with this? Appreciate it in advance! Commented Oct 5, 2020 at 14:43

2 Answers 2

2

Since you're invoking a transformation anyway, it's much simpler to do all the work in XSLT rather than fiddle about with low-level DOM manipulation.

If you use XSLT 3.0 (Saxon) then the stylesheet is simply

<xsl:transform version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:mode on-no-match="shallow-copy"/>
  <xsl:output indent="yes" encoding="utf-8"/>
  <xsl:template match="id"/>
</xsl:transform>

You can supply the input to this transformation as new StreamSource(new StringReader(xmlString)) -- there's no need to construct a DOM first.

It can be done in XSLT 1.0 too (i.e. with Xalan, which comes bundled with the JDK), but is a bit more verbose.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, I am not sure how to use XSLT for this.Could you please elaborate on that.Thank you again!
Well, I've shown you the XSLT code, and you already know how to invoke the JAXP interface which can run an XSLT transformation, so I'm not sure what part you're missing. I could write the code for you, but StackOverflow is for answering questions, not for getting people to write code for you. There are plenty of tutorials on the web about how to invoke a XSLT transformation from Java, and even better, there are plenty of good books.
1

Here is solution using XPath API. In this example all elements "id" inside elements "Identity" are removed (XPath expression "//Identity/id"). If you want to remove all id elements, change it to "//id".

import java.io.StringReader;
import java.io.StringWriter;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.InputSource;

// function for XML serialization
public static String serialize(Document document) {
        removeWhitespaces(document.getDocumentElement());
        try (StringWriter writer = new StringWriter()) {
            StreamResult result = new StreamResult(writer);
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            transformer.setOutputProperty(OutputKeys.METHOD, "xml");
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
            transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
            transformer.transform(new DOMSource(document), result);
            return writer.toString();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    
    // helper function for stripping whitespaces
    public static void removeWhitespaces(Element element) {
        NodeList children = element.getChildNodes();
        for (int i = children.getLength() - 1; i >= 0; i--) {
            Node child = children.item(i);
            if (child instanceof Text
                && ((Text) child).getData().trim().isEmpty()) {
                element.removeChild(child);
            } else if (child instanceof Element) {
                removeWhitespaces((Element) child);
            }
        }
    }

Main code:

    // parse XML
    DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
    Document doc = db.parse(new InputSource(new StringReader(xml)));
    
   // find id elements
    XPathExpression xpath = XPathFactory.newInstance().newXPath().compile("//Identity/id");
    NodeList nodes = (NodeList)xpath.evaluate(doc, XPathConstants.NODESET);

    // remove found elements
    for(int i = 0; i < nodes.getLength(); i ++) {
        Node node = nodes.item(i);
        node.getParentNode().removeChild(node);
    }
    
    // serialize and output document
    String result = serialize(doc);
    System.out.println(result);

3 Comments

Thanks, I am using Jdom 2.0.Is it possible with that? Also, i was getting error at transformer.transform(new DOMSource(document), result); earlier.It said this constructor DOMSource(document) is undefined.Could you please confirm on the same.
Sorry, I'm not familiar with Jdom. I suppose an error with DOMSource constructor happens because javax.xml.transform.dom.DOMSource takes as parameter org.w3c.dom.Document, not jdom Document implementation.
Imho, working with XPathExpressions is the cleanest and shortest way to read and manipulate nodes!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.