1
votes

I've created a simple xml file here:

http://roberthan.host56.com/productsNew.xml

which is quite simple, the root node is [products] while all other element nodes are [product]. Under each [product] node, there are two child nodes, [code] and [name], so it basically looks like:

[product]
     [code]ddd[/code]
     [name]ssss[/name]
   [/product]

I've also written up the following Java code to parse this XML file and take out the text content of the [product] node, and add it to a JComboBox.

docBuilder = docFactory.newDocumentBuilder();
doc = docBuilder.parse("http://roberthan.host56.com/productsNew.xml");

    NodeList productNodes = doc.getElementsByTagName("product");

        productlist.clear();
        for (i = 0; i < productNodes.getLength(); i++) 
        {


            Node childNode = productNodes.item(i);

            if (childNode.hasChildNodes()) {
                NodeList nl = childNode.getChildNodes();


                Node nameNode = nl.item(2);
                productlist.add(nameNode.getTextContent());

            }

        }


final JComboBox productComboB = new JComboBox();
Iterator iterator = productlist.iterator();

while(iterator.hasNext())
{
 productComboB.addItem(iterator.next().toString());
}

The code is quite straightforward, I firstly parse the xml and get all the product nodes and put them into a nodelist, and the productList is an arrayList. I loop through the all the [product] nodes, for each of them, if it has child nodes, then I take the second child node (which is the [name] node) and put the text content of it in the array list, and finally, I loop through the arrayList and add each item to the combo box.

The problem I got is, if I select the [code] child node, which means "Node nameNode = nl.item(1)", it will work perfectly; however, if I change that item(1) to item(2) to extract all the [name] nodes, the combo box will have a drop down list, but all the items are blank, like I have inserted 10 empty strings.

Also, if I try to add a "Hello World" string into the combo box after the above code, the "Hello World" item will appear after the 10 empty items.

I have spent the whole afternoon debugging this but still no breakthrough, the XML is actually quite simple and the Java is straightforward too. Could anyone share some thoughts with me on this please. Thanks a lot!

2
Your best bet is to do some debugging to try to isolate the region in your code causing the error, then if a solution doesn't fall out, post a small compilable runnable program that demonstrates the problem. - Hovercraft Full Of Eels
Also, have you considered extracting from your Document using XPath? - Hovercraft Full Of Eels
@Hovercraft I have, but this function has to be done in Java, could you suggest a way for me to incorporate XPath to Java classes? - Kevin
??? XPath is implemented in core Java - Hovercraft Full Of Eels
I don't know how you can sleep at night with code randomly indented like that - Brad Mace

2 Answers

4
votes

It is because the node list contains text nodes also.

If you add the following snippet to your code you will find that

for(int j = 0;j<nl.getLength();j++){
    System.out.println(nl.item(j).getNodeName());
}

It will give the following output for each iteration of the product

#text
code
#text
name
#text

This means you have to get the 3rd element to get the name node.

Node nameNode = nl.item(3);

But I'll suggest you to use XPath to solve this problem.

NodeList nodelist = XPathAPI.selectNodeList(doc, "//products/product/name");
for (int i = 0; i < nodelist.getLength(); i++) {
    productlist.add(nodelist.item(i).getTextContent());
}
1
votes

XPath using this expression will easily solve your problem:

String XPATH_EXPRESSION1 = "//name/text()";

e.g.,

  public static final String PRODUCTS_NEW = "http://roberthan.host56.com/productsNew.xml";
  public static final String XPATH_EXPRESSION1 = "//name/text()";

  public XmlFun() {
     URL productsUrl;
     try {
        productsUrl = new URL(PRODUCTS_NEW);
        List<String> nameList = xPathExtract(productsUrl.openStream());
     } catch (MalformedURLException e) {
        e.printStackTrace();
     } catch (IOException e) {
        e.printStackTrace();
     } catch (ParserConfigurationException e) {
        e.printStackTrace();
     } catch (SAXException e) {
        e.printStackTrace();
     } catch (XPathExpressionException e) {
        e.printStackTrace();
     }
  }

  private List<String> xPathExtract(InputStream inStream) throws ParserConfigurationException, SAXException, IOException, XPathExpressionException {
     DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
     DocumentBuilder builder = domFactory.newDocumentBuilder();
     Document domDoc = builder.parse(inStream);

     XPathFactory xFactory = XPathFactory.newInstance();
     XPath xpath = xFactory.newXPath();

     XPathExpression xExpr = xpath.compile(XPATH_EXPRESSION1);
     NodeList nodes = (NodeList)xExpr.evaluate(domDoc, XPathConstants.NODESET);

     List<String> resultList = new ArrayList<String>();
     for (int i = 0; i < nodes.getLength(); i++) {
        String node = nodes.item(i).getNodeValue();
        resultList.add(node);
     }

     return resultList;
  }