1

I have an xml file as such

<?xml version="1.0" encoding="UTF-8"?>
<folder name="c">
  <folder name="program files"> 
      <folder name="uninstall information" />
  </folder>
  <folder name="users"/>
</folder>

I want to print out "c", "program files", "uninstall information" and "users" what i finally want to do is to print out only values of the name attribute with string starting from u , therefore users and uninsall information. But i have not been able to print all the values out, Below is my code where you can see i have tried to ways but no success so far.

  public static Collection<String> folderNames(String xml, char startingLetter) throws Exception {
        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
        try {
            DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
            FileInputStream fis = new FileInputStream("src/main/resources/test.xml");
            org.xml.sax.InputSource is = new InputSource(fis);
            Document doc = documentBuilder.parse(is);
            NodeList nodeList = doc.getElementsByTagName("*");
            for(int i =0; i < nodeList.getLength(); i++) {
                Node node = nodeList.item(i);
 /// Tried this
                if(node.getNodeType() == Node.ELEMENT_NODE) {
                    String value = node.getTextContent();
                    System.out.println("value:::" +value);
                }
/// tried this
//                Element element = (Element)nodeList.item(i);
//                NamedNodeMap attributes = element.getAttributes();
//                     Node nodeValue1 = nodeList.item(i);
//                    System.out.println(nodeValue1.getAttributes().item(i));
            }
         } catch (Exception e) {
            e.getMessage();
        }
        return Collections.EMPTY_LIST;
     }

for speedy test my imported classes looks like test

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

My approach without using getElementByTagsName

 Document doc = documentBuilder.parse(is);
            NodeList nodeList = doc.getElementsByTagName("folder");
            for(int i =0; i < nodeList.getLength(); i++) {
               if (nodeList.item(i).hasChildNodes()) {
               for(int i1 = 0; i1 < nodeList.item(i).getChildNodes().getLength(); i1++) {
                   Node node = nodeList.item(i).getChildNodes().item(i);
                   System.out.println(node.getAttributes().item(i));
                   }
               }
                Node nodeValue1 = nodeList.item(i);
                System.out.println(nodeValue1.getAttributes().item(i));

This isnt complete but it will require a recursive call, due to hierarchy in the xml

3
  • What do you believe value = node.getTextContent() does, and why do you believe that? The question makes the impression that you want the value of the name attribute. Commented Apr 23, 2020 at 1:45
  • yes i want the value of the name attributes Commented Apr 23, 2020 at 1:48
  • Then why isn't there a element.getAttribute("name") anywhere in the code? Commented Apr 23, 2020 at 1:50

2 Answers 2

1

Example of printing all folder names starting with u:

String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + 
             "<folder name=\"c\">\n" + 
             "  <folder name=\"program files\">\n" + 
             "      <folder name=\"uninstall information\" />\n" + 
             "  </folder>\n" + 
             "  <folder name=\"users\"/>\n" + 
             "</folder>";
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document doc = documentBuilder.parse(new InputSource(new StringReader(xml)));
NodeList nodeList = doc.getElementsByTagName("folder");
for (int i = 0; i < nodeList.getLength(); i++) {
    Element element = (Element) nodeList.item(i);
    String name = element.getAttribute("name");
    if (name.startsWith("u"))
        System.out.println(name);
}

Output

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

4 Comments

thanks, could you speak on my approach, what i just added now, also i am just learning how the getelementbytags works, i believe their are cases where we will need to go into childNodes to get element, this might need a recursive approach
@valik Javadoc of getElementsByTagName() says: Returns a NodeList of all the Elements in document order with a given tag name and are contained in the document. --- In this case, that means all elements named folder, regardless of depth. No recursion needed. Otherwise, how did you think the code could print uninstall information?
yes i understand this now, i was saying it could still be done by recursion (poor approach ofcourse) considering getElementByTagName() exists.
@valik You're not making sense: There is no getElementByTagName() (singular), only getElementsByTagName() (plural), and considering it exists and you're using it, there is no need for recursion. --- Yes, it can be done with recursion, but then you wouldn't be using getElementsByTagName() for that, you'd use getChildNodes() or a combination of getFirstChild() and getNextSibling().
1

You almost had it. First you have to identify the XML element, which you did.

        if(node.getNodeType() == Node.ELEMENT_NODE) {
            String value = node.getTextContent();
            System.out.println("value:::" +value);
        }

but instead of getting invoking getTextContent(), you need to find the attribute in that element. Some variation of the below. Of course, if there is more than one attribute you will need to accomodate looking at them all (using node.getAttributes().getLength()):

            if(node.getNodeType() == Node.ELEMENT_NODE) {
                if (node.getAttributes() != null) {
                    String name = node.getAttributes().item(0).getNodeName();
                    String value = node.getAttributes().item(0).getNodeValue();
                    System.out.println("attribute name:::" +name + "   value:::" +value);
                }
            }

1 Comment

Relying on name attribute to be the first attribute is a bad idea, and entirely unnecessary, since DOM has this very useful getAttribute(String name) method, as already shown in the other answer.

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.