Итак, я новичок в выражениях 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());
}
}
Проблема, с которой я столкнулся с этим кодом, заключается в том, что он возвращает мне только значения нулевой вместо этих текстовых значений. Не могли бы вы заметить, что я здесь делаю не так?
В API W3C DOM вы используете значение узла для узлов элемента, определенное как значение null, поэтому здесь нет ничего удивительного. Вы можете использовать getTextContent() вместо getNodeValue().
@Andersson, где именно добавить эту строку. Извините, я новичок в этой концепции.
Мартин был довольно ясен: заменять getNodeValue () с getTextContent ().
@MartinHonnen getNodeValue () работает, но показывает значения несколько раз
Ваш документ имеет смешанное содержимое (т.е. элемент emp имеет и текст, и дочерний элемент (элемент age)), кроме того, корневой элемент также выбирается с помощью XPath, который вы использовали. Поэтому вам нужно будет более подробно объяснить, как вы хотите получить этот результат, который вы показали (или следуйте первоначальному предложению в первом комментарии, чтобы вывести строку полного элемента employee).
@MartinHonnen, как было предложено, я добавил немного больше деталей о том, какой результат я ожидаю. Что касается первого комментария, я действительно не уверен, где добавить эту строку.
Вы хотите, чтобы этот текст 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/….
@MartinHonnen Спасибо. Да, я хочу, чтобы это было одной строкой. Сотрудник - это просто корневой элемент. Так что это произойдет только один раз. Однако <emp> может встречаться несколько раз внутри <employee>
@MartinHonnen Есть ли что-нибудь еще, что мне нужно изменить в коде, поскольку я получаю эту ошибку: не удается преобразовать #STRING в NodeList!
Что ж, да, если вы используете метод, который возвращает String, вам нужно использовать его как String, а не как NodeList.
@MartinHonnen Я пробовал это сделать, и он показывает ошибку




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