【问题标题】:A question on how to solve the string problem in Java关于如何解决Java中的字符串问题的一个问题
【发布时间】:2010-12-17 03:41:27
【问题描述】:

我在这里创建了一个简单的 xml 文件:

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

这很简单,根节点是[products],而所有其他元素节点都是[product]。在每个【产品】节点下,有【代码】和【名称】两个子节点,所以基本上是这样的:

[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得到所有的product节点,放到一个nodelist中,productList就是一个arrayList。我遍历所有 [product] 节点,对于每个节点,如果它有子节点,那么我取第二个子节点(即 [name] 节点)并将其文本内容放入数组列表中,最后,我循环遍历 arrayList 并将每个项目添加到组合框中。

我遇到的问题是,如果我选择[code]子节点,意思是“Node nameNode = nl.item(1)”,它会完美运行;但是,如果我将 item(1) 更改为 item(2) 以提取所有 [name] 节点,组合框将有一个下拉列表,但所有项目都是空白的,就像我插入了 10 个空字符串一样。

另外,如果我尝试在上述代码之后的组合框中添加一个“Hello World”字符串,则“Hello World”项将出现在 10 个空项之后。

我花了一个下午的时间调试这个,但仍然没有突破,XML实际上很简单,Java也很简单。有人可以和我分享一些想法吗?非常感谢!

【问题讨论】:

  • 最好的办法是进行一些调试以尝试隔离代码中导致错误的区域,然后如果没有解决方案,请发布一个小型可编译可运行程序来演示该问题。
  • 另外,您是否考虑过使用 XPath 从您的文档中提取数据?
  • @Hovercraft 我有,但是这个功能必须在 Java 中完成,你能建议我将 XPath 合并到 Java 类的方法吗?
  • ??? XPath 在核心 Java 中实现的
  • 我不知道你怎么能用这样随机缩进的代码晚上睡觉

标签: java xml xpath


【解决方案1】:

这是因为节点列表也包含文本节点。

如果您将以下 sn-p 添加到您的代码中,您会发现

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

它将为产品的每次迭代提供以下输出

#text
code
#text
name
#text

这意味着您必须获得第三个元素才能获得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());
}

【讨论】:

  • 我现在正在学习 XSLT,我遇到了在 XSLT 处理器中空白将被视为文本节点的部分。那么我可以将我们在这里拥有的东西等同于一般的 XSLT 吗?
  • 我不是 XSLT 方面的专家,但据我所知,不同的 xml 解析器处理空白的方式不同。所以我认为它可能与 XSLT 处理器相同。
【解决方案2】:

使用此表达式的 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;
  }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-03-19
    • 2011-07-23
    • 2020-07-25
    • 1970-01-01
    • 1970-01-01
    • 2019-05-25
    • 2019-09-01
    • 1970-01-01
    相关资源
    最近更新 更多