如何指定 XPath 以生成包含与其父元素属性连接的元素文本的列表

Posted

技术标签:

【中文标题】如何指定 XPath 以生成包含与其父元素属性连接的元素文本的列表【英文标题】:How to specify XPath to produce a list containing element text concatenated with its parent element attribute 【发布时间】:2021-08-21 22:50:34 【问题描述】:

我还是 XPath 的新手,并试图处理具有一些复杂结构的大型数据集。以下是一些示例数据:

...
<div2 id="n104226" key="to/lmh" type="main">
    <headword extent="suff" lang="greek">τόλμη</headword>,
    <gen lang="greek">ἡ</gen>,
    <sense id="n104226.0" n="A">v. τόλμα.</sense>
</div2>
<div2 id="n104244" key="*to/maros" type="main">
    <headword extent="full" lang="greek">Τόμαρος</headword>,
    <gen lang="greek">ὁ</gen>,
    <sense id="n104244.0" n="A">v. Τομοῦροι.</sense>
</div2>
<div2 id="n104248" key="tomei=on" type="main">
    <headword extent="suff" lang="greek">τομεῖον</headword>,
    <gen lang="greek">τό</gen>,
</div2>
...

我想生成一个词条列表,以及父元素 (div2) 上的 key 属性,如下所示:

...
τόλμη, to/lmh
Τόμαρος, *to/maros
τομ-εῖον, tomei=on
...

我在这里查看了许多关于 SO 的帖子以获得想法,例如:

How to get the attribute value of a parent element in Xpath if Child element exists? Xpath query to get the parent Element text and its child element attribute values? How to get a specifc information for an XML file Parse XML based on attributes and text values of related nodes Concatenate multiple node values in xpath

我曾多次尝试定义 XPath 表达式来执行此操作,但均未成功。我一直在使用 XML Copy Editor 的 Evaluate XPath 功能尝试这些表达式,但最终我想在我的 C# 代码中使用该表达式,所以我都尝试了。以下是我尝试过的一些表达方式:

//div2/string-join(@key | headword, "<>")
//div2/concat(@key, ' ', headword/text())
//div2/concat(@key, ',', headword[1])

每次XML Copy Editor都会给我这个错误信息:

无法评估 XPath:第 0 行出错:表达式无效

同时,.NET 抛出如下形式的异常:

"'//div2/concat(@key, ',', headword1)' 的令牌无效。"

IIRC,当我的同事在 Oxygen 中尝试时,这最后一个为他工作。

我在XML Copy Editor中试过这个:

concat(//div2/@key, ',', //div2/headword/text())

它没有产生错误消息,但它只产生了第一个结果。

谁能帮我解决这个问题?

为了完整起见,这里是我的 C# 代码的片段:

XPathNavigator navigator = ResourceDocument.CreateNavigator();
XPathNodeIterator nodeSetTmp =
    navigator.Select(@"//div2/headword[1]/text()", nsmgr);

感谢您的任何建议...


更新

这里还有一些我尝试过的 XPath 表达式(但没用):

//div2 ! string-join((headword, " ", @key), "") //div2/string-join((headword, " ", @key), "") //div2/concat(headword, " ", @key)

【问题讨论】:

【参考方案1】:

你想要的结果与你的努力不匹配......但这可能是一个小错误。 (切换@keyheadword

这两个 XPath 工作正常:

//div2/concat(@key, ' ', headword/text())
//div2/concat(@key, ',', headword[1])

氧气正在显示这个结果:

to/lmh,τόλμη
*to/maros,Τόμαρος
tomei=on,τομεῖον

也许您使用的 XPath 引擎是 1.0?

作为替代方案,您可以尝试使用非常简单的 xslt 1.0,如下所示:

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="text" />
  
  <xsl:template match="div2">
    <xsl:value-of select="concat(headword[1]/text(),', ',@key)"/>
  </xsl:template>
  
</xsl:transform>

会给出这个结果。

  τόλμη, to/lmh
  Τόμαρος, *to/maros
  τομεῖον, tomei=on

【讨论】:

"也许您使用的 XPath 引擎是 1.0?"是的,事实证明,由于各种原因,我们还不能升级。所以这是它不起作用的主要原因。谢谢,@Siebe。

以上是关于如何指定 XPath 以生成包含与其父元素属性连接的元素文本的列表的主要内容,如果未能解决你的问题,请参考以下文章

如何指定一个元素以具有一个属性,该属性说明它在 XML 模式中包含多少个子元素?

XPath怎样根据一个元素定位另外一个元素?

xpath使用属性元素定位,包含 and ornot

如何使用 python 为 Web 元素生成 Xpath(在我的脚本中运行时)?

Python解析库lxml与xpath用法总结

如何在具有 xmlns 属性的 xml 中使用 xpath 获取特定的嵌套元素? [复制]