XPath 从多个节点获取文本

Posted

技术标签:

【中文标题】XPath 从多个节点获取文本【英文标题】:XPath get text from multiple nodes 【发布时间】:2012-12-30 12:41:01 【问题描述】:

我需要创建一个字符串数组,其名称文本来自:

<xs:element name="xyz" type="xs:string/>

<xs:element name="bla" type="xs:string/>

...

如何查询“xyz”、“bla”等?

可能是你见过的最糟糕的代码,但无论如何:

NodeList result1 = (NodeList) xPath.evaluate("//@name", example, XPathConstants.NODESET);

for(int i=0; i<result1.getLength();i++) 
   System.out.println("read 1:" +result1.item(i));

//console output is:
//read 1:name="xyz"
//read 1:name="bla"

ArrayList<String> liste; 
liste = new ArrayList<String>(result1.getLength());
for (int i=0; i<result1.getLength();i++)
   String read=xPath.evaluate("//@name", example);
   liste.add(read);
   System.out.println("read 2: "+read);      


System.out.println("complete list: " +liste);

//console output is:
//read 2:name="xyz"
//read 2:name="xyz"
//complete list: [xyz, xyz]

感谢您的帮助,这样就可以了:

(以防万一......如果有人在这里寻找解决方案)

NodeList result = (NodeList) xPath.evaluate("//@name", example, XPathConstants.NODESET);
liste = new ArrayList<String>(result.getLength());
for(int i=0; i<result.getLength();i++)
liste.add(result.item(i).getNodeValue());

return(liste);

【问题讨论】:

我试过了,但它只提供第一项.. 对于上面的例子,它只会写 xyz 你的代码在哪里?选择单个节点和多个节点的方法很可能有不同的方法,而您使用的是前者。 取决于您使用的是什么,可能您可能会遍历结果集。 【参考方案1】:
import static javax.xml.xpath.XPathConstants.NODESET;
import static org.apache.commons.lang3.StringUtils.firstNonEmpty;
import static org.apache.commons.lang3.StringUtils.trim;

/**
 * Returns first non-empty result
 * 
 * @param xpaths
 * @return first non-empty result or null if result not found
 */
public static String xpathValue(Document document, String... xpaths) 
    List<String> result = xpathValues(document, xpaths);
    if (result.isEmpty())
        return null;
    if (result.size() == 1)
        return result.get(0);
    throw new IllegalStateException(format("Non-unique result: %s", result));


/**
 * Returns first non-empty result
 * 
 * @param xpaths
 * @return first non-empty result or empty list if result not found
 */
public static List<String> xpathValues(Document document, String... xpaths) 
    XPathFactory f = XPathFactory.newInstance();
    return stream(xpaths)
            .map(xpath -> evaluateXpath(document, f, xpath))
            .filter(CollectionUtils::isNotEmpty)
            .findFirst().orElse(emptyList());


private static List<String> evaluateXpath(Document document, XPathFactory f, String xpath) 
    try 
        NodeList result = (NodeList) f.newXPath().evaluate(xpath, document, NODESET);
        List<String> liste = new ArrayList<String>(result.getLength());
        for (int i = 0; i < result.getLength(); i++) 
            Node item = result.item(i);
            liste.add(firstNonEmpty(trim(item.getTextContent()), item.getNodeValue()));
        
        return liste;
     catch (XPathExpressionException e) 
        throw new IllegalArgumentException("Cannot evaluate xpath: " + xpath, e);
    

【讨论】:

【参考方案2】:

看起来您已成功检索结果列表,但随后您遍历它们并在每次迭代期间重新评估 XPath。看起来值在您第一次循环通过 result1 时正确打印出来,所以您为什么不直接替换它:

String read=xPath.evaluate("//@name", example);

用这个:

String read = result1.item(i).toString();

【讨论】:

以上是关于XPath 从多个节点获取文本的主要内容,如果未能解决你的问题,请参考以下文章

如何从 XmlNode 实例中获取 xpath

从 XML 节点 java 生成/获取 xpath

Xpath 从兄弟节点的父节点获取值

使用 XSLT 基于 ID 从多个 xPath 中选择 XML 节点

xpath选择兄弟节点返回上一级和选择多个属性

使用xpath从xml获取子节点值