html - XPath 选择嵌套 XML 结构中的最后一个节点?
问题描述
假设我有这个 XML:
<div>
<div>
<div>
<div>
"Hello2"
</div>
</div>
</div>
</div>
但我的模板可能会改变,我希望div
元素所在的深度灵活。例子:
<div>
<div>
<div>
"Hello3"
</div>
</div>
</div>
那么如何从这个嵌套的 XML 结构中获取 XML 中最后一个元素的内部文本呢?
解决方案
那么如何从这个嵌套的 XML 结构中获取 XML 中最后一个元素的内部文本呢?
从发布的 XML 文档看来,实际要求的是:
如何获取XML 文档中最内层元素的字符串值
一、XPath 1.0 / XSLT 1.0 解决方案:
此 XPath 表达式在求值时:
//*[not(*)]
选择文档中没有另一个元素作为子元素的所有元素。
(//*[not(*)])[last()]
选择最后一个这样的最内层节点。
用单个 XPath 1.0 表达式不可能找到“最深的元素”—— 可以通过简单的 XSLT 1.0 转换来做到这一点。下面的 XSLT 1.0 转换将 XML 文档的最后一个最里面的元素复制到输出:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:key name="kElemByDepth" match="*" use="count(ancestor::*)"/>
<xsl:template match="/">
<xsl:variable name="vMaxDepth">
<xsl:apply-templates select="//*[not(*)]" mode="getMax">
<xsl:sort select="count(ancestor::*)" data-type="number" order="descending"/>
</xsl:apply-templates>
</xsl:variable>
<xsl:copy-of select="key('kElemByDepth', $vMaxDepth)[last()]"/>
</xsl:template>
<xsl:template match="*" mode="getMax">
<xsl:if test="position() = 1">
<xsl:value-of select="count(ancestor::*)"/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
当此转换应用于以下 XML 文档时:
<div>
<div>
<div>
<div>
"Hello2"
</div>
<div>
"Hello3"
</div>
</div>
</div>
<div>
"Hello1"
</div>
</div>
产生了想要的正确结果:
<div>
"Hello3"
</div>
如果您只需要此元素的字符串值,只需替换:
<xsl:copy-of select="key('kElemByDepth', $vMaxDepth)[last()]"/>
和
<xsl:copy-of select="normalize-space(key('kElemByDepth', $vMaxDepth)[last()])"/>
二、纯 XPath 2.0 解决方案
使用这个 XPath 2.0 表达式:
normalize-space(//*[not(*)]
[not(count(ancestor::*) < //*[not(*)]/count(ancestor::*))][last()])
基于 XSLT 2.0 的验证:
此转换评估上述 XPath 2.0 表达式并将此评估的结果复制到输出:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<xsl:sequence select=
"normalize-space(//*[not(*)]
[not(count(ancestor::*) < //*[not(*)]/count(ancestor::*))][last()])"/>
</xsl:template>
</xsl:stylesheet>
当应用于同一个 XML 文档(上图)时,同样会产生同样正确的、想要的结果:
"Hello3"
推荐阅读
- javascript - 无法从网站多次请求
- java - 骑士在爪哇的岩石之旅
- javascript - 如何在 NextJS 中添加自定义脚本包
- sql - 将具有相同 ID 但多列的“是”/“否”值不同的多行组合成一行,显示所有“是”/“否”值
- c++ - 用于多维张量的 TensorflowLite C API 输入缓冲区布局
- django - 如何为这个模型制作一个表单,让用户能够为每个问题选择选项 - Django
- r - 在跳过缺失值的同时计算数字序列
- python - Django中的持久连接?
- java - 为什么我收到错误“无法解析“x”中的方法“x””?
- sas - 在 SAS 中动态连接变量