Почему мое выражение XPath в Java возвращает слишком много дочерних элементов? - PullRequest
1 голос
/ 28 марта 2009

У меня есть следующий XML-файл:

<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<config>
 <a>
  <b>
   <param>p1</param> 
   <param>p2</param> 
  </b>
 </a>
</config>

и код xpath для получения параметров моего узла:

Document doc = ...;
XPath xpath = XPathFactory.newInstance().newXPath();
XPathExpression expr = xpath.compile("/config/a/b");
Object o = expr.evaluate(doc, XPathConstants.NODESET);
NodeList list = (NodeList) o;

но оказывается, что список узлов (list) имеет 5 дочерних элементов, включая "\t\n", вместо двух. Что-то не так с моим кодом? Как я могу просто получить мои два узла?

Спасибо!

Ответы [ 5 ]

5 голосов
/ 28 марта 2009

Когда вы выбираете /config/a/b/, вы выбираете все дочерние элементы b, что включает три текстовых узла и два элемента. То есть, учитывая ваш XML выше и показывая только рассматриваемый фрагмент:

<b>
 <param>p1</param> 
 <param>p2</param> 
</b>

первым дочерним элементом является текст (пробел), следующий за <b> и предшествующий <param>p1 .... Второй дочерний элемент - это первый элемент param. Третий дочерний элемент - это текст (пробел) между двумя элементами param. И так далее. Пробелы не игнорируются в XML, хотя многие формы обработки XML игнорируют его.

У вас есть пара вариантов:

  1. Измените ваше выражение xpath, чтобы оно выбирало только узлы элементов, как предложено Тедом Дзюбой, или
  2. Зацикливание на пяти возвращенных узлах и выбор только нетекстовых узлов.

Вы могли бы сделать что-то вроде этого:

for (int i = 0; i < nodes.getLength(); i++) {
    if (nodes.item(i).getNodeType() != Node.TEXT_NODE) {
        System.out.println(nodes.item(i).getNodeValue());
    }
}

Вы можете использовать тип узла, чтобы выбрать только узлы элемента или удалить текстовые узлы.

4 голосов
/ 28 марта 2009

так что xpath выглядит так: /config/a/b/*/text(). И вывод для:

for (int i = 0; i < nodes.getLength(); i++) {
        System.out.println(nodes.item(i).getNodeValue());
    }

будет как ожидалось: p1 и p2

2 голосов
/ 28 марта 2009

Как насчет

/config/a/b/*/text()/..

1 голос
/ 11 октября 2011
import org.w3c.dom.*;

import javax.xml.xpath.*;

import javax.xml.parsers.*;

import java.io.IOException;

import org.xml.sax.SAXException;

public class TestClient_XPath {

    public static void main(String[] args) throws ParserConfigurationException,
            SAXException, IOException, XPathExpressionException {

        DocumentBuilderFactory domFactory = DocumentBuilderFactory
                .newInstance();
        domFactory.setNamespaceAware(true);
        DocumentBuilder builder = domFactory.newDocumentBuilder();

        Document doc = builder.parse("yourfile.xml");
        XPath xpath = XPathFactory.newInstance().newXPath();

        XPathExpression xPathExpression = xpath.compile("/a/b/c");

        Object res = xPathExpression.evaluate(doc);

        System.out.println(res.toString());
    }

}

Кажется, что Xalan и Xerces встроены в rt.jar.

Не включает ксерсис и ксалану.

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4624775

0 голосов
/ 28 марта 2009

Я не уверен, но не должен / config / a / b просто вернуть b ? / config / a / b / param должен возвращать два param узла ...

Может ли проблема быть проблемой? Конечно, вы получите обратно полученный узел И все его дочерние элементы. Так что вам просто нужно взглянуть на первый элемент, а не на его дочерние элементы.

Но я могу быть совершенно неправ, потому что я обычно использую Xpath для навигации по деревьям DOM (HtmlUnit).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...