XPath, работающий с смешанным контентом - PullRequest
1 голос
/ 22 сентября 2011

Как извлечь текст такого элемента через XPath:

<document>
  some text
     <subelement>subelement text</subelement>
  postscript
</document>

Выражение XPath:

/document

возвращает текст узла документа и текст всех его подузлов:

some text         subelement text    postscript

В то время как выражение XPath:

/document/text()

возвращает только первый текстовый узел:

some text

то есть отсутствует "postscript".

Вопрос
Есть ли способ получить текст всех текстовых узлов, которые являются непосредственными сыновьями <document>?

Постскриптум
Очень сфокусированный пример, если вы хотите проверить себя, скопируйте в основной метод и исправьте импорт.

    DocumentBuilder dbuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();

    String xml = "<?xml version='1.0' encoding='UTF-8'?>" +
                 "<document>"
                 + "some text into document"
                 + "    <subelement>"
                 + "        some text into SUBelement"
                 + "    </subelement>"
                 + "POSTSCRIPT"
                 + "</document>";

    //i'm forced to use an InputSource because parse doesn't take readers directly :-(
    Document doc = dbuilder.parse(new InputSource(new StringReader(xml)));

    //usual way to get an xpath
    XPath xp = XPathFactory.newInstance().newXPath();

    System.out.println(xp.evaluate("/document", doc));

    System.out.println(xp.evaluate("/document/text()",doc));

Ответы [ 4 ]

2 голосов
/ 22 сентября 2011

Это даст вам все текстовые дети. В общем, использование toString() или методов, которые пытаются вернуть представления String, приведет к разрывам при работе с DOM. Всегда безопаснее «сделать это полностью / сделать это правильно».

        NodeList list = (NodeList) xp.evaluate("/document/text()", doc, XPathConstants.NODESET);
        for (int i = 0; i < list.getLength(); i++) {
            System.out.println(list.item(i).getNodeValue());
        }
2 голосов
/ 22 сентября 2011

Только что протестировано

xp.evaluate("/document/text()",doc, XPathConstants.NODESET)

действительно возвращает все текстовые дочерние элементы, но вы выполняете

xp.evaluate("/document/text()", doc, XPathConstants.STRING)

, который, кажется, преобразует только первый узел в узле, установленном в строку. Поэтому, возможно, вам нужно найти другой способ конвертировать NodeSet в String.

1 голос
/ 22 сентября 2011

В то время как выражение XPath:

/document/text()

возвращает только первый текстовый узел:

some text into document

то есть "postscript" отсутствует.

Вышеупомянутое выражение XPath возвращает все дочерние элементы текстового узла /document, но метод XPath.evaluate () без третьего аргумента преобразует свой результат в строку. При этом он, по-видимому, действует как <xsl:value-of>, поскольку он преобразует только первый узел в результирующем наборе узлов.

Чтобы напечатать значение всех дочерних узлов текстового узла, укажите XPathConstants.NODESET в качестве 3-го аргумента для XPath.evaluate (). Это даст вам набор узлов текстовых узлов в виде NodeList . Затем вы можете просмотреть их и распечатать каждый. Или вы можете попробовать передать NodeList напрямую в println () и посмотреть, что он печатает. : -)

1 голос
/ 22 сентября 2011

XPath /document/text() вернет все дочерние текстовые узлы элемента document.В вашем примере: some text и postscript.Я думаю (я не знаю классов Java) System.out.println автоматически преобразует набор узлов в строковое представление, в этом случае он просто возвращает 1-й узел.

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