2010-12-17 44 views
1
解決字符串問題的問題

我創建這裏簡單的XML文件:如何在Java中

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

這是很簡單的,根節點[產品],而所有其他元素節點是[產品]。在每個[產品]節點,有兩個子節點,[代碼]和[名],因此,它基本上是這樣的:

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

我也寫了下面的Java代碼來解析這個XML文件並取出[product]節點的文本內容,並將其添加到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()); 
} 

的代碼是相當簡單的,我首先解析XML,並得到所有產品的節點,並把它們放入一個節點列表,以及productList的是的ArrayList。我循環遍歷所有[product]節點,對於它們中的每一個,如果它有子節點,那麼我將第二個子節點(它是[name]節點)並將它的文本內容放入數組列表中,最後,我遍歷arrayList並將每個項目添加到組合框。

我得到的問題是,如果我選擇[代碼]子節點,這意味着「節點nameNode = nl.item(1)」,它將完美工作;但是,如果我將項目(1)更改爲項目(2)以提取所有[名稱]節點,組合框將有一個下拉列表,但所有項目都是空白的,就像我插入了10個空字符串一樣。

此外,如果我嘗試在上面的代碼後面添加一個「Hello World」字符串到組合框中,「Hello World」項目將出現在10個空項目之後。

我花了整個下午來調試這個,但仍然沒有什麼突破,XML實際上很簡單,Java也很簡單。請有人可以與我分享一些想法。非常感謝!

+0

最好的辦法是做一些調試嘗試該地區在你的代碼找出導致錯誤,那麼如果一個解決方案不出來,發佈一個小的可編譯的可運行程序來演示這個問題。 – 2010-12-17 03:46:40

+0

另外,您是否考慮使用XPath從文檔中提取? – 2010-12-17 03:52:55

+0

@Hovercraft我有,但這個功能必須用Java完成,你能否提供一種方法讓我將XPath合併到Java類中? – Kevin 2010-12-17 03:54:17

回答

4

這是因爲節點列表還包含文本節點。

如果添加下面的代碼片段到你的代碼,你會發現,

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

它會給下面的輸出爲產品的每一次迭代

#text 
code 
#text 
name 
#text 

這意味着你必須讓第3個元素獲取name節點。

Node nameNode = nl.item(3); 

但我建議你使用XPath來解決這個問題。

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

這是我見過的最美妙的教訓,謝謝! – Kevin 2010-12-17 04:03:11

+0

我現在正在研究XSLT,並且我遇到了將空白視爲XSLT處理器中的文本節點的部分。那麼我是否可以將我們這裏的所有內容等同於XSLT? – Kevin 2010-12-20 19:00:39

+0

我不是XSLT方面的專家,但據我所知不同的XML解析器以不同的方式處理空白。所以我認爲它可能和XSLT處理器一樣。 – 2010-12-21 02:42:49

1

的XPath使用這個表達式將會輕鬆解決你的問題:

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

例如,

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; 
    }