Добрый день. Есть подобный xml:
<?xml version="1.0" encoding="windows-1251"?>
<head>
<date>22.07.2019</date>
</head>
<rec num="1">
<main_info>
<aux>
<inn>
<inn_no>132465</inn_no>
</inn>
</aux>
</main_info>
<data1>
<id>1111</id>
</data1>
</rec>
<rec num="2">
<main_info>
<aux>
<inn>
<inn_no>2222222</inn_no>
</inn>
</aux>
</main_info>
<data1>
<id>987</id>
</data1>
</rec>
<rec num="3">
<main_info>
<aux>
<inn>
<inn_no>132465</inn_no>
</inn>
</aux>
</main_info>
<data1>
<id>8888</id>
</data1>
<data2>
<tag2>
<id>777</id>
</tag2>
</data1>
</rec>
Можно ли через XPath из него вытащить следующее:
132465 1111 (пусто)
2222222 987 (пусто)
132465 8888 777
Здравствуйте, .alex, Вы писали:
A>Добрый день. Есть подобный xml:
Это не валидный XML, у XML должен быть один элемент верхнего уровня (а ещё элемент data2 закрыт тегом data1).
A>Можно ли через XPath из него вытащить следующее:
Можно. Если считать, что элемент верхнего уровня называется root, то выражение /root/rec вытащит элементы rec, вы делаете цикл по ним, выражения main_info/aux/inn/inn_no , data1/id , data2/tag2/id вычисленные относительно элемента rec вытащат соответствующие строки.
Пример кода на Java, который это делает:
String xml = "" +
"<?xml version=\"1.0\"?>\n" +
"<root>\n" +
" <head>\n" +
" <date>22.07.2019</date>\n" +
" </head>\n" +
"\n" +
" <rec num=\"1\">\n" +
" <main_info>\n" +
" <aux>\n" +
" <inn>\n" +
" <inn_no>132465</inn_no>\n" +
" </inn>\n" +
" </aux>\n" +
" </main_info>\n" +
"\n" +
" <data1>\n" +
" <id>1111</id>\n" +
" </data1>\n" +
" </rec>\n" +
"\n" +
" <rec num=\"2\">\n" +
" <main_info>\n" +
" <aux>\n" +
" <inn>\n" +
" <inn_no>2222222</inn_no>\n" +
" </inn>\n" +
" </aux>\n" +
" </main_info>\n" +
"\n" +
" <data1>\n" +
" <id>987</id>\n" +
" </data1>\n" +
" </rec>\n" +
"\n" +
" <rec num=\"3\">\n" +
" <main_info>\n" +
" <aux>\n" +
" <inn>\n" +
" <inn_no>132465</inn_no>\n" +
" </inn>\n" +
" </aux>\n" +
" </main_info>\n" +
"\n" +
" <data1>\n" +
" <id>8888</id>\n" +
" </data1>\n" +
"\n" +
"\n" +
" <data2>\n" +
" <tag2>\n" +
" <id>777</id>\n" +
" </tag2>\n" +
" </data2>\n" +
" </rec>\n" +
"</root>";
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document document = documentBuilder.parse(new InputSource(new StringReader(xml)));
XPathFactory xPathFactory = XPathFactory.newInstance();
XPath xPath = xPathFactory.newXPath();
NodeList recNodes = (NodeList) xPath.evaluate("/root/rec", document, XPathConstants.NODESET);
for (int i = 0; i < recNodes.getLength(); i++) {
Node rec = recNodes.item(i);
System.out.print(xPath.evaluate("main_info/aux/inn/inn_no", rec));
System.out.print(" ");
System.out.print(xPath.evaluate("data1/id", rec));
System.out.print(" ");
System.out.print(xPath.evaluate("data2/tag2/id", rec));
System.out.println();
}
Здравствуйте, vsb, Вы писали:
vsb>Здравствуйте, .alex, Вы писали:
A>>Добрый день. Есть подобный xml:
vsb>Это не валидный XML, у XML должен быть один элемент верхнего уровня (а ещё элемент data2 закрыт тегом data1).
A>>Можно ли через XPath из него вытащить следующее:
vsb>Можно. Если считать, что элемент верхнего уровня называется root, то выражение /root/rec вытащит элементы rec, вы делаете цикл по ним, выражения main_info/aux/inn/inn_no , data1/id , data2/tag2/id вычисленные относительно элемента rec вытащат соответствующие строки.
Да, xml сам руками набивал, ошибся... Спасибо за ответ, собственно говоря я и хотел узнать можно ли делать XPath запрос, не только относительно документа, а относительно какой-нибудь произвольной ноды, получается можно). Надо бы почитать мануал)
Сделал вот так на PowerShell, вроде работает, но может где-то есть ошибка?...
$doc = [xml]@'
<root>
<head>
<date>22.07.2019</date>
</head>
<rec num="1">
<main_info>
<aux>
<inn>
<inn_no>132465</inn_no>
</inn>
</aux>
</main_info>
<data1>
<id>1111</id>
</data1>
</rec>
<rec num="2">
<main_info>
<aux>
<inn>
<inn_no>2222222</inn_no>
</inn>
</aux>
</main_info>
<data1>
<id>987</id>
</data1>
</rec>
<rec num="3">
<main_info>
<aux>
<inn>
<inn_no>132465</inn_no>
</inn>
</aux>
</main_info>
<data1>
<id>8888</id>
</data1>
<data2>
<tag2>
<id>777</id>
</tag2>
</data2>
</rec>
</root>
'@
$rec_nodes = $doc.SelectNodes("root/rec")
ForEach ($rec in $rec_nodes)
{
echo $rec
$inn_nodes = $rec.SelectNodes("main_info/aux/inn/inn_no")
ForEach ($inn in $inn_nodes)
{
echo ("`t" + $inn.InnerText)
}
$id_nodes = $rec.SelectNodes("data1/id")
ForEach ($id in $id_nodes)
{
echo ("`t" + $id.InnerText)
}
$id2_nodes = $rec.SelectNodes("data2/tag2/id")
ForEach ($id2 in $id2_nodes)
{
echo ("`t" + $id2_nodes.InnerText)
}
}