Search code examples
javaxmlparsingdomsax

insert a string in a particular position in an XML file


I have an XML file (client_23.xml) as shown below. And I have a String variable out which I need to insert a particular spot in below XML. This is not my full XML as I have lot of other nested stuff under which function tag will be in and it is not consistent since this XML is getting generated through code so I nee

<?xml version="1.0"?>
<clients>
    <!-- some other code here -->

    <function>
    </function>

    <function>
    </function>

    <function>
        <name>data_values</name>
        <variables>
            <variable>
            <name>temp</name>
            <type>double</type>
            </variable>
        </variables>
        <block>
            <opster>temp = 1</opster>   
        </block>
    </function>
</clients>

I need to parse the above XML and find a function whose name is data_values and then insert out string variable in <block> tag. This is not my full XML as I have lot of other nested stuff under which function tag will be in and it is not consistent since this XML is getting generated through code so I need to parse and iterate and find it and then put it.

So final xml will look like this:

<?xml version="1.0"?>
<clients>
    <!-- some other code here -->

    <function>
    </function>

    <function>
    </function>

    <function>
        <name>data_values</name>
        <variables>
            <variable>
            <name>temp</name>
            <type>double</type>
            </variable>
        </variables>
        <block>
            <!-- new stuff added and old things were gone -->
            <opster>hello = world</opster>
            <opster>abc = def</opster>
        </block>
    </function>
</clients>

Below is the code I got but I am not able to understand how can I put out variable inside data_values function in a block tag.

StringBuilder out = new StringBuilder();
// some data in out variable, properly formatted with new lines.

String location = key.getPathName();
String clientIdPath = location + "/" + "client_23.xml";
File fileName = new File(clientIdPath);

DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document document = documentBuilder.parse(fileName);

NodeList dataValueFunction = document.getElementsByTagName("function");
// I have started iterating but I am not able to understand how to insert "out"
// variable inside block
for (int i = 0; i < dataValueFunction.getLength(); i++) {
    Node node = dataValueFunction.item(i);
    System.out.println(node.getNodeName());
    NodeList childList = node.getChildNodes();
    for (int j = 0; j < childList.getLength(); j++) {
        Node node1 = childList.item(j);
        if (node1 != null && node1.getNodeName().equalsIgnoreCase("name")
                        && node1.getTextContent().equalsIgnoreCase("data_values")) {
            // now what should I do here?
        }
    }
}

Solution

  • Check this question. You can use XPath expressions to locate correct function tag and update it using Xpath.

    How to update XML using XPath and Java

    Here is a quick code.

    public static void main(String[] args) {
        try {
            FileInputStream file = new FileInputStream(new File("data.xml"));
            List<String> outs = Arrays.asList(new String[] { "hello = world", "abc = def" });
            DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
    
            DocumentBuilder builder = builderFactory.newDocumentBuilder();
    
            Document xmlDocument = builder.parse(file);
    
            XPath xPath = XPathFactory.newInstance().newXPath();
    
            System.out.println("*************************");
            String expression = "//clients/function/name[text()='data_values']";
            System.out.println(expression);
            Node nameTag = (Node) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODE);
    
            for (int i = 0; i < nameTag.getParentNode().getChildNodes().getLength(); i++) {
                if (nameTag.getParentNode().getChildNodes().item(i).getNodeName().equals("block")) {
                    System.out.println("GOT BLOCK");
                    nameTag.getParentNode().removeChild(nameTag.getParentNode().getChildNodes().item(i));
                    Node node = xmlDocument.createElement("block");
    
    
    
                    nameTag.getParentNode().appendChild(node);
                    for (String out : outs) {
                        Node newNode = xmlDocument.createElement("opster");
                        newNode.setTextContent(out);
    
                        node.appendChild(newNode);
                    }
    
                }
            }
            TransformerFactory tFactory = TransformerFactory.newInstance();
            Transformer transformer = tFactory.newTransformer();
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
            DOMSource source = new DOMSource(xmlDocument);
            StreamResult result = new StreamResult(System.out);
            transformer.transform(source, result);
    
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (XPathExpressionException e) {
            e.printStackTrace();
        } catch (TransformerConfigurationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (TransformerException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }