mpv1504
mpv1504

Reputation: 31

Editing XML file with Java

I am new in Java and XML. I need to modify a part of this XML file using a Java program :

<?xml version="1.0" encoding="UTF-8"?>
<Traduction>
  <Entrée>
    <Word1>Word1</Word1>
    <N1>0</N1>
    <N2>0</N2>
    <Word2>Word2</Word2>
  </Entrée>
  <Sortie>
    <Word1>Word1</Word1>
    <N1>0</N1>
    <N2>0</N2>
    <Word2>Word2</Word2>
  </Sortie>
</Traduction>

I wanted to use this code in Eclipse :

try {
    String filepath = "/home/user/Trad/ex1.xml";
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    DocumentBuilder builder = factory.newDocumentBuilder();
    Document document = builder.parse(filepath);

    Node Traduction = document.getChildNodes().item(0);
    Node Sortie = Traduction.getChildNodes().item(1);

    Sortie.getChildNodes().item(0).setTextContent("AAA");
    Sortie.getChildNodes().item(1).setTextContent("001");
    Sortie.getChildNodes().item(2).setTextContent("002");
    Sortie.getChildNodes().item(3).setTextContent("BBB");

    TransformerFactory transformerFactory = TransformerFactory.newInstance();
    Transformer transformer = transformerFactory.newTransformer();
    DOMSource source = new DOMSource(document);
    StreamResult result = new StreamResult(new File(filepath));
    transformer.transform(source, result);
}

catch (ParserConfigurationException pce) {
    pce.printStackTrace();
    } 
catch (TransformerException tfe) {
    tfe.printStackTrace();
    } 
catch (IOException ioe) {
    ioe.printStackTrace();
    } 
catch (SAXException sae) {
    sae.printStackTrace();
    }

But I get this result, which is not what I want :

<?xml version="1.0" encoding="UTF-8" standalone="no"?><Traduction>
  <Entrée>AAA<Word1>001</Word1>002<N1>BBB</N1>
    <N2>0</N2>
    <Word2>Word2</Word2>
  </Entrée>
  <Sortie>
    <Word1>Word1</Word1>
    <N1>0</N1>
    <N2>0</N2>
    <Word2>Word2</Word2>
  </Sortie>
</Traduction>

I would like to get :

<?xml version="1.0" encoding="UTF-8"?>
<Traduction>
  <Entrée>
    <Word1>Word1</Word1>
    <N1>0</N1>
    <N2>0</N2>
    <Word2>Word2</Word2>
  </Entrée>
  <Sortie>
    <Word1>AAA</Word1>
    <N1>001</N1>
    <N2>002</N2>
    <Word2>BBB</Word2>
  </Sortie>
</Traduction>

What should I modify in my Java code to get this ?

Upvotes: 2

Views: 287

Answers (2)

Sachin Gupta
Sachin Gupta

Reputation: 8358

As already suggested, Dom Node can be of any type. You can use getElementsByTagName method to be sure of that.

E.g.:

try {
            String filepath = "/home/user/Trad/ex1.xml";
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document document = builder.parse(filepath);

            Element sortie = (Element) document.getElementsByTagName("Sortie").item(0);

            sortie.getElementsByTagName("Word1").item(0).setTextContent("AAA");
            sortie.getElementsByTagName("N1").item(0).setTextContent("001");
            sortie.getElementsByTagName("N2").item(0).setTextContent("002");
            sortie.getElementsByTagName("Word2").item(0).setTextContent("BBB");

            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            DOMSource source = new DOMSource(document);
            StreamResult result = new StreamResult(new File(filepath));
            transformer.transform(source, result);
        }

        catch (ParserConfigurationException pce) {
            pce.printStackTrace();
        } catch (TransformerException tfe) {
            tfe.printStackTrace();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        } catch (SAXException sae) {
            sae.printStackTrace();
        }

Upvotes: 2

Tamas Rev
Tamas Rev

Reputation: 7166

The trick is that DOM nodes can be other than the element nodes. I.e. for the whitespaces between <Entree> and <Word1> it creates a TextNode. You need to go through the NodeList and check for node name or node type.

In the code example you can see example for both. Please note that this code is a bit unstructured. For production quality code you might want to refactor it a little.

Node Traduction = document.getChildNodes().item(0);
NodeList traductionChildNodes = Traduction.getChildNodes();
Node Sortie = null;
for (int i = 0; i < traductionChildNodes.getLength(); i++) {
    Node node = traductionChildNodes.item(i);
    // here we check the node name
    if ("Sortie".equals(node.getNodeName())) {
        Sortie = node;
        break;
    }
}

NodeList sortieChildNodes = Sortie.getChildNodes();
// we got the texts in an array so we can access them one after another
String[] texts = new String[] {"AAA", "001", "002", "BBB"};
// i is for the nodes, j is for the 
for (int nodeIndex = 0, textIndex = 0; nodeIndex < sortieChildNodes.getLength(); nodeIndex++) {
    Node node = sortieChildNodes.item(nodeIndex);
    // here we check the node type
    if (node.getNodeType() == Node.ELEMENT_NODE) {
        node.setTextContent(texts[textIndex++]);
    }
}

Alternatively, you might consider using XPath because that makes ad-hoc XML processing a little more intuitive.

Upvotes: 1

Related Questions