Я пытаюсь использовать Xpath для синтаксического анализа строки xml, но я не знаю, как использовать выражение для получения того, что я хочу.
У меня есть следующий xml-контент:
<root1>
<root2>
<A>something</A>
<B>something</B>
<C>
<D>
<E>DataE</E>
<F>DataF</F>
<G>something</G>
<H>something</H>
<I>
<J>
<K>DataK</K>
<L>DataL</L>
</J>
</I>
</D>
<D>
<E>DataE_ERROR</E>
<F>DataF</F>
<G>something</G>
<H>something</H>
<I>
<J>
<K>DataK</K>
<L>DataL</L>
</J>
</I>
</D>
</C>
</root2>
</root1>
Я хотел бы получить значение F, K, L, когда значение E является DataE, например.
Я использую для этого Xpath, но я не могу найти хорошее выражение!
вот мой код Java:
public void getit()
{
String xml = "The xml above";
DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
DocumentBuilder b = f.newDocumentBuilder();
Document d = b.parse(new InputSource(new StringReader(xml)));
d.getDocumentElement().normalize();
// No idea ! how can i make it work by testing the value of E
String expression = "//E/text()|//F/text()|//K/text()|//L/text()";
XPath xPath = XPathFactory.newInstance().newXPath();
Object result = xPath.compile(expression).evaluate(d, XPathConstants.NODESET);
NodeList nodes = (NodeList) result;
for (int i = 0; i < nodes.getLength(); i++) {
System.out.println(nodes.item(i).getNodeValue());
}
}
Просто чтобы я мог гарантировать, что запрос работает, я изменил XML-пример следующим образом...
<root1>
<root2>
<A>something</A>
<B>something</B>
<C>
<D>
<E>DataE</E>
<F>DataF 1</F>
<G>something</G>
<H>something</H>
<I>
<J>
<K>DataK 1</K>
<L>DataL 1</L>
</J>
</I>
</D>
<D>
<E>DataE_ERROR</E>
<F>DataF 2</F>
<G>something</G>
<H>something</H>
<I>
<J>
<K>DataK 2</K>
<L>DataL 2</L>
</J>
</I>
</D>
</C>
</root2>
</root1>
Магия здесь...
String expression = "//F[ancestor::D/E[text()='DataE']]|//K[ancestor::D/E[text()='DataE']]|//L[ancestor::D/E[tex
В принципе, это читает...
Найдите любой узел F
, у которого есть предок, содержащий D
с дочерним элементом E
, текст которого равен DataE
или...
Теперь это важно, вы можете использовать ../
чтобы найти родительский узел, но K
и L
похоронены в под-узлах, и я не уверен, что они могут быть более глубокими или неглубокими, поэтому я пошел на этот метод.
Возможно, вам придется немного его доработать, но я считаю, что отношения D/E
были важны.
С этим (и приведенным ниже примером) я смог создать следующий вывод...
Found DataF 1
Found DataK 1
Found DataL 1
Пример Runnable:
public class TestXPath {
public static void main(String[] args) {
String xml = "The xml above";
try {
DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
DocumentBuilder b = f.newDocumentBuilder();
Document d = b.parse(new File("Values.xml"));
d.getDocumentElement().normalize();
String expression = "//F[ancestor::D/E[text()='DataE']]|//K[ancestor::D/E[text()='DataE']]|//L[ancestor::D/E[text()='DataE']]";
XPath xPath = XPathFactory.newInstance().newXPath();
Object result = xPath.compile(expression).evaluate(d, XPathConstants.NODESET);
NodeList nodes = (NodeList) result;
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
System.out.println("Found " + node.getTextContent());
}
} catch (ParserConfigurationException | SAXException | IOException | XPathExpressionException | DOMException exp) {
exp.printStackTrace();
}
}
}
//J[ancestor::K[text()='DataK']]
или что-то может сделать это ...