Как извлечь все значения, на которые указывает XPath?

У меня есть ниже XML

<test>
    <nodeA>
           <nodeB>key</nodeB>
           <nodeC>value1</nodeC>
    </nodeA>
    <nodeA>
           <nodeB>key</nodeB>
           <nodeC>value2</nodeC>
    </nodeA>
</test>

Как объединить и получить все значения в xpath /test/nodeA/nodeC? Мой ожидаемый результат в этом сценарии будет value1value2

Из того, что я прочитал, я не уверен, что это возможно с xpath, но спасибо за вашу помощь.

PS: я использую VTD-XML из Ximpleware для анализа того же в Java. Любое решение на основе Java также приветствуется. В настоящее время мое решение Java дает только первое значение, т.е. value1

4 ответа

Решение

XPath вернет NodeList который вы можете перебрать и объединить:

StringBuilder concatenated = new StringBuilder():
XPath xpath = XPathFactory.newInstance().newXPath();
String expression = "/test/nodeA/nodeC/text()";
InputSource inputSource = new InputSource("sample.xml");
NodeList nodes = (NodeList) xpath.evaluate(expression, inputSource, XPathConstants.NODESET);
for(int i = 0; i < nodes.getLength(); i++) {
    concatenated.append(nodes.item(i).getTextContent());
}

Вот отличная реализация (в 2 строки кода!) С использованием XmlSlurper

def xml = new groovy.util.XmlSlurper().parse(new File('sample.xml'))
print xml.nodeA*.nodeC.join("")

Выходы

value1value2

Я не использую groovy в производственном коде, но для локального осмотра это здорово. У меня часто бывают небольшие отличные утилиты в файлах сборки Gradle.

Если вы хотите, чтобы одно выражение XPath возвращало строку с конкатенацией выбранных значений, вам понадобится XPath 2.0 (или более поздняя версия) или XQuery 1.0 (или более поздняя версия), где вы можете выполнить string-join(/test/nodeA/nodeC, ''), XPath 1.0 не имеет выразительной силы, чтобы дать вам строку, но, конечно, как уже показано в другом ответе, вы можете перебирать выбранные узлы и объединять выбранные значения на главном языке, таком как Java.

Вот как я бы сделал это с VTD-XML...

import com.ximpleware.*;


public class concat {
     public static void main(String[] s) throws VTDException{
         VTDGen vg = new VTDGen();
         if (!vg.parseFile("input.xml", false))
             return;
         VTDNav vn = vg.getNav();
         AutoPilot ap = new AutoPilot(vn);
         ap.selectXPath("/test/*/nodeC/text()");
         StringBuilder sb = new StringBuilder(100);
         int i=0;
         while((i=ap.evalXPath())!=-1){
             sb.append(vn.toString(i));
         }
         System.out.println(sb.toString());
     }

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