Как получить все узлы с текстом с помощью XPath в Java

Итак, я новичок в выражениях Xpath и использую их с Java. Я пытаюсь проанализировать XML-файл, чтобы получить все узлы с текстом между тегами. Например, если у меня есть XML как

<employee>
   <emp>John <age>25</age>
   </emp>
   <salary> 1000
   </salary>
</employee>

Тогда я должен получить

John 25 1000

т.е. только текстовое содержимое между любыми тегами без дублирования. Я следую этому руководство здесь, чтобы использовать выражение Xpath для получения желаемых значений. Я написал следующий фрагмент:

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;;

public class xpathTest {

public static void main(String[] args) throws Exception
{
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    factory.setNamespaceAware(true); // never forget this!
    DocumentBuilder builder = factory.newDocumentBuilder();
    Document doc = builder.parse("TestXmlFile.xml");

    //Create XPath

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

    XPathExpression expr = xpath.compile("//*[text()]"); // to get all all nodes having some text

    Object result = expr.evaluate(doc, XPathConstants.NODESET);
    NodeList nodes = (NodeList) result;
    for (int i = 0; i < nodes.getLength(); i++) {
        System.out.println(nodes.item(i).getNodeValue());

    }
}

Проблема, с которой я столкнулся с этим кодом, заключается в том, что он возвращает мне только значения нулевой вместо этих текстовых значений. Не могли бы вы заметить, что я здесь делаю не так?

Если вам нужно все текстовое содержимое узла employee, попробуйте string(normalize-space(//employee))

Andersson 01.11.2018 16:47

В API W3C DOM вы используете значение узла для узлов элемента, определенное как значение null, поэтому здесь нет ничего удивительного. Вы можете использовать getTextContent() вместо getNodeValue().

Martin Honnen 01.11.2018 16:57

@Andersson, где именно добавить эту строку. Извините, я новичок в этой концепции.

A Beginner 01.11.2018 17:14

Мартин был довольно ясен: заменять getNodeValue () с getTextContent ().

VGR 01.11.2018 17:20

@MartinHonnen getNodeValue () работает, но показывает значения несколько раз

A Beginner 01.11.2018 17:30

Ваш документ имеет смешанное содержимое (т.е. элемент emp имеет и текст, и дочерний элемент (элемент age)), кроме того, корневой элемент также выбирается с помощью XPath, который вы использовали. Поэтому вам нужно будет более подробно объяснить, как вы хотите получить этот результат, который вы показали (или следуйте первоначальному предложению в первом комментарии, чтобы вывести строку полного элемента employee).

Martin Honnen 01.11.2018 17:56

@MartinHonnen, как было предложено, я добавил немного больше деталей о том, какой результат я ожидаю. Что касается первого комментария, я действительно не уверен, где добавить эту строку.

A Beginner 01.11.2018 18:12

Вы хотите, чтобы этот текст John 25 1000 был одной строкой? Есть более одного элемента employee? XPath из первого комментария (то есть xpath.compile("string(normalize-space(//employee))")) даст вам (на стороне Java) String, содержащий это значение John 25 1000 первого элемента employee в документе. Вы могли бы использовать перегрузку evaluate с одним аргументом docs.oracle.com/javase/8/docs/api/javax/xml/xpath/….

Martin Honnen 01.11.2018 18:19

@MartinHonnen Спасибо. Да, я хочу, чтобы это было одной строкой. Сотрудник - это просто корневой элемент. Так что это произойдет только один раз. Однако <emp> может встречаться несколько раз внутри <employee>

A Beginner 01.11.2018 18:27

@MartinHonnen Есть ли что-нибудь еще, что мне нужно изменить в коде, поскольку я получаю эту ошибку: не удается преобразовать #STRING в NodeList!

A Beginner 01.11.2018 18:29

Что ж, да, если вы используете метод, который возвращает String, вам нужно использовать его как String, а не как NodeList.

Martin Honnen 01.11.2018 18:42

@MartinHonnen Я пробовал это сделать, и он показывает ошибку

A Beginner 01.11.2018 19:11
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
12
661
0

Другие вопросы по теме