У меня есть xml файл:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<fields>
<field>
<name>ID</name>
<shortcode>id</shortcode>
<display>true</display>
<table_id>1</table_id>
</field>
<field>
<name>Name</name>
<shortcode>name</shortcode>
<display>true</display>
<table_id>1</table_id>
</field>
<field>
<name>ID</name>
<shortcode>id</shortcode>
<display>true</display>
<table_id>2</table_id>
</field>
<field>
<name>Name</name>
<shortcode>name</shortcode>
<display>true</display>
<table_id>2</table_id>
</field>
<field>
<name>ID</name>
<shortcode>id</shortcode>
<display>true</display>
<table_id>3</table_id>
</field>
<field>
<name>Name</name>
<shortcode>name</shortcode>
<display>true</display>
<table_id>3</table_id>
</field>
</fields>
Я хочу получить все "полевые" элементы, которые имеют table_id = 1 (или 2, 3,..). Я попробовал код ниже, но это неправильно:
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
domFactory.setNamespaceAware(true); // never forgot this
DocumentBuilder builder = domFactory.newDocumentBuilder();
Document doc = builder.parse(filePath);
XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();
XPathExpression expr = xpath.compile("fields/field[table_id=1]");
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).getChildNodes().item(i).getTextContent());
NodeList childNodes = nodes.item(i).getChildNodes();
for (int j = 0; j < childNodes.getLength(); j++) {
System.out.println(childNodes.item(j).getTextContent());
}
System.out.println(childNodes.getLength()); // **why 9 nodes**
}
Я не знаю, почему это 9? Результат, который я хочу, - это 4 узла. Пожалуйста, помогите мне!
В дочерние узлы входят текстовые узлы - элемент
<field>
<name>ID</name>
<shortcode>id</shortcode>
<display>true</display>
<table_id>1</table_id>
</field>
действительно имеет девять дочерних узлов, состоящих из четырех дочерних узлов элемента плюс пять белых текстовых узлов между <field>
и <name>
, </table_id>
и </field>
, а также между закрывающим тегом одного дочернего элемента и открывающий тег следующего.
Если вы заботитесь только о дочерних элементах, а не о дочерних узлах, вы должны фильтровать только те дочерние узлы, которые являются instanceof Element
, или, альтернативно, вы можете извлекать только элементы с другим выражением XPath
XPathExpression childEltsExpr = xpath.compile("*");
а затем в цикле for
NodeList childElements = (NodeList)childEltsExpr.evaluate(nodes.item(i),
XPathConstants.NODESET);
Потому что у вас также есть текстовые узлы (пробелы между тегами). Вы должны попытаться выбрать только дочерние элементы, являющиеся узлом элемента. например, с node.getNodeType()