2

UPDATE i was specifically targeting staff under some root node, not all "staff" elements in the whole document. i forgot to mention this important detail in the question. sorry guys.

i found this answer to my question:
getElementsByTagName

But with this data:

<one>
<two>
    <three>
        <company>

            <staff id="1001">
                <firstname>Golf</firstname>
                <lastname>4</lastname>
                <nickname>Schnecke</nickname>
                <salary>1</salary>
            </staff>
            <staff id="2001">
                <firstname>Audi</firstname>
                <lastname>R8</lastname>
                <nickname>Rennaudi</nickname>
                <salary>1111111</salary>
            </staff>
            <staff id="2002">
                <firstname>Skoda</firstname>
                <lastname>xyz</lastname>
                <nickname>xyz</nickname>
                <salary>0.1</salary>
            </staff>

        </company>
    </three>
</two>
</one>

and this code:

public static void parseXML2() {
    File fXmlFile = new File("src\\main\\java\\staff.xml");
        DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder dBuilder = null;
    try {
        dBuilder = dbFactory.newDocumentBuilder();
    } catch (ParserConfigurationException ex) {
        Logger.getLogger(MyParser.class.getName()).log(Level.SEVERE, null, ex);
    }
        Document doc = null;
    try {
        doc = dBuilder.parse(fXmlFile);
    } catch (SAXException ex) {
        Logger.getLogger(MyParser.class.getName()).log(Level.SEVERE, null, ex);
    } catch (IOException ex) {
        Logger.getLogger(MyParser.class.getName()).log(Level.SEVERE, null, ex);
    }
    System.out.println("test");
       System.out.println(doc.getElementsByTagName("company").item(0).getTextContent());

}

i dont get just one staff element, but all of them. how come?
i was expecting to get:

                Golf
                4
                Schnecke
                1

but instead i get this:

                Golf
                4
                Schnecke
                1


                Audi
                R8
                Rennaudi
                1111111


                Skoda
                xyz
                xyz
                0.1

looks like your post is mostly code, please add more details...yes the details are there.

J. Doe
  • 80
  • 1
  • 1
  • 7

3 Answers3

0

You have a line of code which gets the text content from the first company.

 System.out.println(doc.getElementsByTagName("company").item(0).getTextContent());

This gets all the text content in the first company node which in this case is the data inside 3 staff elements. If you want to select the first staff element, you can either select it by name or by getting the first child of the company.

MartinByers
  • 1,240
  • 1
  • 9
  • 15
  • your answer was of course right, but my question was not really formulated that good and i can only give one green arrow. sorry. – J. Doe Aug 22 '17 at 08:12
  • @J. Doe your first comment says I am wrong, then your next comment says I am right, please can you remove the first comment to avoid future confusion. – MartinByers Aug 22 '17 at 08:53
0

You are almost there. If you want to get the text contents of the first staff node, then get the elements by that tag name:

System.out.println(doc.getElementsByTagName("staff").item(0).getTextContent());
                                         // ^^^^^^

Update

In case you want to get the first staff node under company, then you can find them with node type and node name checks. Here is a rudimentary loop to do this:

    Node companyNode = doc.getElementsByTagName("company").item(0);
    NodeList companyChildNodes = companyNode.getChildNodes();
    for (int i = 0; i < companyChildNodes.getLength(); i++) {
        Node node = companyChildNodes.item(i);
        if (node.getNodeType() == Node.ELEMENT_NODE && Objects.equals("staff", node.getNodeName())) {
            System.out.println(node.getTextContent());
            break;
        }
    }

You might want to refactor the for loop into a separate method.

You can use XPATH too. I think it's more concise:

    XPathFactory xPathfactory = XPathFactory.newInstance();
    XPath xpath = xPathfactory.newXPath();
    XPathExpression expr = xpath.compile("//company/staff[1]");
    NodeList nl = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
    System.out.println(nl.item(0).getTextContent());

Explanation:

  • //company selects all the company tags, regardless where they are in the xml. It's the // that ignores the rest of the xml structure.
  • //company/staff selects all the staff tags that are under company tag.
  • [0] selects the first such item.
Tamas Rev
  • 7,008
  • 5
  • 32
  • 49
  • this would get all "staff" items in the whole document is suspect? this is precisely what i do not want. also i could have clarified that in my question. i need all "staff" under a specific root node – J. Doe Aug 22 '17 at 07:43
  • Updated the post with two alternative solutions which do exactly what you need. – Tamas Rev Aug 22 '17 at 07:59
  • in your first example i changed this line: if (node.getNodeType() == Node.ELEMENT_NODE && node.getNodeName().equals("staff")) { not really sure where the "Objects" comes from – J. Doe Aug 22 '17 at 08:11
  • `java.util.Objects` was introduced in java 7. It provides convenience methods. E.g. `Objects.equals()` is a null-safe wrapper around the `equals` method. It's unnecessary here. However, generally I prefer to use `Objects.equals()` so my code will be safe no matter what. – Tamas Rev Aug 22 '17 at 08:38
0

If your xml has a format like you mentioned, and with this line of code,

System.out.println(doc.getElementsByTagName("company").item(0).getTextContent();

you are printing ALL contents under the COMPANY tag name, thus its gonna print EVERYTHING in company, if you want to select to print only 1st staff, change tagname in the sysout to "staff" and item variable to (0,1,2,3 -> index of wanted staff)

System.out.println(doc.getElementsByTagName("staff").item(0).getTextContent();

i havent tried this out, but i think its gonna work

Luka Špoljarić
  • 988
  • 1
  • 10
  • 23