1

I new to java and XML. My goal is to get info from my XML file and save it to a string array for later use in my code for testing my website. The XML contains elements of each page divided to 3 categories: Name, Attribute, Text. My first step was just to isolate the data i want and print it, and already got stuck.

Here is an example for my XML file (the original has a lot more nodes using the same structure):

<?xml version="1.0" encoding=""ISO-8859-1""?>
<config>
  <HomeScreenName>
    <Logo>Logo</Logo>
    <Mainimage>Main image</Mainimage>
    <Maintext>Main text</Maintext>
    <Backupbutton>Backup button</Backupbutton>
    <ViewBackupbutton>View Backup button</ViewBackupbutton>
    <Version>Version</Version>
    <Cancelaccountbutton>Cancel account button</Cancelaccountbutton>
  </HomeScreenName>
  <HomeScreenAttributes>
    <Logo>/html/body/div[1]/div[1]</Logo>
    <Mainimage>//*[@id="img-content"]</Mainimage>
    <Maintext>/html/body/div[1]/div[3]/h3</Maintext>
    <Backupbutton>/html/body/div[1]/div[3]/div[1]/a/span</Backupbutton>
    <ViewBackupbutton>/html/body/div[1]/div[3]/div[2]/a/span</ViewBackupbutton>
    <Version>//*[@id="version"]</Version>
    <Cancelaccountbutton>//*[@id="unregister"]/p</Cancelaccountbutton>
  </HomeScreenAttributes>
  <HomeScreenText>
    <Logo />
    <Mainimage />
    <Maintext>Secure backup</Maintext>
    <Backupbutton>Back Up</Backupbutton>
    <ViewBackupbutton>View Your Backups</ViewBackupbutton>
    <Version>Version 1.0.3</Version>
    <Cancelaccountbutton />
  </HomeScreenText>
 </config>

From this XML i would like to create 4 arrays: First with just the name of each node: array1 = [HomeScreenName, HomeScreenAttributes, HomeScreenText]

Then i want an array for each node attributes: something like this: array2(from HomeScreenName) = [Logo, Main image, Main text, Backup button, View Backup button, Version, Cancel account button]

I have 2 main problems:

  1. How to get just the data i want and not everything from the XML.

  2. How to save the data (I wanted arrays, but i'm open to suggstions).

Here is the code I have for printing every node in the XML file:

import java.io.File;
import java.io.IOException;
import java.util.List;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

public class readConfigXML{
public static void main(String[] args) 
{

  SAXBuilder builder = new SAXBuilder();
  String folderPath = "C:\\Users\\udi\\Documents\\external\\XML\\";
  String fileName = "configTest.xml";
  String filePath = folderPath + fileName;  
  File xmlFile = new File(filePath);

  try {
        Document document = (Document) builder.build(xmlFile);
        Element rootNode = document.getRootElement();
        List configList = rootNode.getChildren();
        for (int i = 0; i < configList.size(); i++) 
        {
            Element node = (Element) configList.get(i);
            List dataNodes = node.getChildren();
            for (int j = 0; j < dataNodes.size(); ++j) 
            {
                Element dataNode = (Element) dataNodes.get(j);
                System.out.println(dataNode.getName());
            }
        }       
    }
  catch (IOException io) 
  {
    System.out.println(io.getMessage());
  } 
  catch (JDOMException jdomex) 
  {
    System.out.println(jdomex.getMessage());
  }
}
}

Any help will be greatly appreciated!

3 Answers 3

1

Here is a simple code that can achieve what do you wanted. I used Lists in this code. To get just data you wanted, i do not have any other method than checking the nodes than have been read from the xml file.

 import java.io.File;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.List;
    import org.jdom.Document;
    import org.jdom.Element;
    import org.jdom.JDOMException;
    import org.jdom.input.SAXBuilder;



    public class readConfigXML {

 // the nodes that we want to be read
        public static List<String>  wantedNodes  = new ArrayList<String>() ;
// the attributes that we want to be read
        public static List<String>  wantedAttributes= new ArrayList<String>()   ;
        // init the nodes and attributes wanted here
        public static void init(){
            wantedNodes.add("HomeScreenName") ;
            wantedNodes.add("HomeScreenAttributes") ;
            wantedAttributes.add("Logo") ; // ...
        }

        public static void main(String[] args) 
        {
            // here init your wanted nodes and attributes
            init() ;

          SAXBuilder builder = new SAXBuilder();
          String folderPath = "C:\\Users\\udi\\Documents\\external\\XML\\";
          String fileName = "configTest.xml";
          String filePath = folderPath + fileName;  
          File xmlFile = new File(filePath);

          List<String> nodes = new ArrayList<String>() ;
          List<String> attributeNodes = new ArrayList<String>() ;

          try {
                Document document = (Document) builder.build(xmlFile);
                Element rootNode = document.getRootElement();
                List configList = rootNode.getChildren();
                for (int i = 0; i < configList.size(); i++) 
                {
                    Element node = (Element) configList.get(i);
                    // check if this node is wanted  
                    if(wantedNodes.contains(node.getName())){
                        nodes.add(node.getName()) ;
                        List dataNodes = node.getChildren();
                        for (int j = 0; j < dataNodes.size(); ++j) 
                        {
                            Element dataNode = (Element) dataNodes.get(j);
                            // check if this attribute is wanted 
                            if(wantedAttributes.contains(dataNode.getName())){
                                attributeNodes.add(dataNode.getValue()) ;
                            }
                        }
                    }
                }  

            }
          catch (IOException io) 
          {
            System.out.println(io.getMessage());
          } 
          catch (JDOMException jdomex) 
          {
            System.out.println(jdomex.getMessage());
          }
        }

    }
Sign up to request clarification or add additional context in comments.

4 Comments

Thank you! It works great with 3 nodes in the XML, but the real file has 68 nodes. Is there a way to get first all the names of the main nodes and than from that list you can choose what ever node to get attributes?
I don't think there will be a problem with your real file with 68 nodes. it should work the same. yes you can get all the main nodes first and then do what you want with that list. in order to do this you need to add the hole node to nodes list and not only the name. and change the type of the list from string to Element.
After getting a list of elements i will need to manipulate the data and remove all the extra symbols and texts. Is there a way to avoid that?
in my answer, the attributeNodes list contains only the data and no extra symbols. so you can manipulate this list as you want. you don't need any other treatment. if you mean by the symbols those in the data elements like (@, /, ..) you will need to use something like this : str = str.replace("@", "");
0

for the standard JDK package org.w3c.dom(I did not check but perhaps your org.jdom must have the same or similar:

  1. How to get just the data i want and not everything from the XML.

each node has a node type. Then it may have a child of TEXT_NODE type. (Node Type is short and Node interface has constants for types. e.g.

if (dataNode.getNodeType() == Node.TEXT_NODE)

So when you traverse through node children - check if it is a TEXT_NODE then it is a data you need. e.g. Element(node) <Logo>Logo</Logo> has a child text node with value "Logo" and you can get it buy calling: node.getTextContent().

BTW: Be careful with getTextContent() if it is mixed node (with text and other child elements) it will return texts from all children. I do not see it in your example, but first check the Node Type if it is Text Node you are good to use it.

  1. How to save the data (I wanted arrays, but i'm open to suggestions).

It is up to you, but as long as Java does not have dynamic arrays it is better to use List as example LinkedList or ArrayList to capture data from unknown numbers of elements.

If you still want to have array, after all done get array from your resulting List by calling its toArray() method.

Also, for general purpose (if XML tree has unknown or large number of levels you need to use recursion to process child nodes). If it is not a case and you know exactly how deep your XML is, you can be fine to use nested for loops, but still recursion is preferred.

3 Comments

Thank you! I went over your suggestion few times and i'm not sure i understand it. My first goal is the get all the children node names so that i can call their children nodes later. not sure how node type will help with it. And yes, i have to use lists i understand that. Yes again, recursion would be the best way to implement. But since i don't have a way to extract my data, i have nothing to use for recursion.
Maybe I did not understand your question a little. What do you mean under "get just the data i want"? Is it about you need only texts from all nodes and not tags, or do you need texts only from specific nodes? Actually instead of parse XML on your own, it is much better to create Jaxb POJO, give all work to JAxb unmareshaller and do whatever you need from POJO.
Also I did not get a point under "i have nothing to use for recursion." XML is recursive. You have a Node (element), you have child nodes - process each node then recursively process child nodes one by one and so on... what else do you need for recursion?
0

So the best way i could find was to edit my XML so that all the main child nodes will have the same name with different attributes like this:

<Page id="Home">
<Page id="Sign in">

And the code to get all the main Nodes names is this:

public static void main(String[] args) 
{
    String folderPath = "C:\\XML\\";
    String fileName = "2.xml";
    String xmlFile = folderPath + fileName;         
    DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder dBuilder;
    try
    /// gets the main nodes in the config and saves them to a list
    {
        dBuilder = dbFactory.newDocumentBuilder();
        Document doc = dBuilder.parse(xmlFile);
        doc.getDocumentElement().normalize();
        //System.out.println("Root element is:" + doc.getDocumentElement().getNodeName());
        NodeList mainList = doc.getElementsByTagName("Page");
        List<String> list = new ArrayList<String>();
        for (int temp = 0; temp < mainList.getLength(); temp++)
        {
            Node mainNode = mainList.item(temp);
            Element eElement = (Element) mainNode;
            list.add(eElement.getAttribute("id"));
            System.out.println( list.get(temp));
        }
        System.out.println(list);
        System.out.println("----------------------------------------");

    }
    catch(SAXException | ParserConfigurationException | IOException e1)
    {
        e1.printStackTrace();
    }

}

And the output will be:

Home Sign in Register Login and as a list: [Home, Sign in, Register, Login]

Comments

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.