2

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 ?

2
  • read about Java naming convention. propertie names sould start with lowercase character Commented Apr 27, 2017 at 8:07
  • Ok, I am going to correct this. Commented Apr 27, 2017 at 8:23

2 Answers 2

2

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();
        }
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you. It seems to be the most simple solution at first view.
1

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.

1 Comment

Thank you ! Indeed, I didn't know whitespaces could also be nodes. The result is correct now.

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.