gpt4 book ai didi

xml - 从 XML 文档生成 XPATH 到属性级别

转载 作者:行者123 更新时间:2023-12-03 16:54:30 25 4
gpt4 key购买 nike

我有以下 XSLT,它为填充的 XML 文件中的每个元素创建 XPATH。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" indent="no"/>
<xsl:template match="*[not(*)]">
<xsl:for-each select="ancestor-or-self::*">
<xsl:value-of select="concat('/', name())"/>
<xsl:if test="count(preceding-sibling::*[name() = name(current())]) != 0">
<xsl:value-of select="concat('[', count(preceding-sibling::*[name() = name(current())]) + 1, ']')"/>
</xsl:if>
</xsl:for-each>
<xsl:text>&#xA;</xsl:text>
<xsl:apply-templates select="*"/>
</xsl:template>
<xsl:template match="*">
<xsl:apply-templates select="*"/>
</xsl:template>
</xsl:stylesheet>

我想扩展它,以便在“属性”级别生成一个唯一的行。目前,为给定元素生成一个 XPATH 语句,即使它有多个属性。如果一个元素有 3 个属性,我希望每个生成 3 个 XPATH 行。任何想法表示赞赏! :)谢谢

更新

嗨,伊恩,

非常感谢您的帮助。

我需要一项增强功能,我认为这很棘手?

如果元素具有 xsi:type 属性(即是另一种类型的扩展),我需要在 XPATH 中的元素名称中考虑它,而不是作为属性本身(因为它是特殊/保留 XSD 属性)

例如为了
<a>
<b xsi:type="c" attribute1="at1"/>
</a>

我需要:
/a/b[xsi:type="c"]/@attribute1

而不是
/a/b/@type

它目前正在生产哪个?这可能吗?

谢谢!

更新

效果很好,谢谢!最后一个请求很漂亮。 :) 你可以调整它以从 XML 中添加元素或属性 VALUE,用逗号分隔符与 XPATH 部分分隔.....所以是 [XPATH],[VALUE]

最佳答案

我将生成路径的代码提取到另一个模板中,然后从模板中调用元素和属性:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text" indent="no" />

<xsl:template mode="path" match="*">
<xsl:for-each select="ancestor-or-self::*">
<xsl:value-of select="concat('/', name())" />
<xsl:if test="count(preceding-sibling::*[name() = name(current())]) != 0">
<xsl:value-of select="concat('[',
count(preceding-sibling::*[name() = name(current())]) + 1, ']')" />
</xsl:if>
</xsl:for-each>
</xsl:template>

<xsl:template match="*">
<xsl:if test="not(*)">
<!-- this element has no children, print its path -->
<xsl:apply-templates mode="path" select="." />
<xsl:text>&#xa;</xsl:text>
</xsl:if>
<xsl:apply-templates select="@*|*" />
</xsl:template>

<xsl:template match="@*">
<!-- for an attribute, print the path to its containing element ... -->
<xsl:apply-templates mode="path" select=".." />
<!-- ... followed by "/@attributename" -->
<xsl:value-of select="concat('/@', name(), '&#xa;')" />
</xsl:template>
</xsl:stylesheet>

XPath 数据模型的一个奇怪之处在于,虽然属性节点不被认为是其宿主元素节点的子节点,但元素被认为是其属性节点的父节点。

更新:处理 xsi:type要求,您应该能够将该逻辑添加到您当前的兄弟计数代码中,以区别对待类型化元素。并添加您需要合适的值 value-of在适当的地方。
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:output method="text" indent="no" />

<xsl:template mode="path" match="*">
<xsl:for-each select="ancestor-or-self::*">
<xsl:value-of select="concat('/', name())" />
<!-- for typed elements, include the type in the path -->
<xsl:if test="@xsi:type">
<xsl:text>[@xsi:type = '</xsl:text>
<xsl:value-of select="@xsi:type" />
<xsl:text>']</xsl:text>
</xsl:if>
<xsl:if test="count(preceding-sibling::*[name() = name(current()) and
@xsi:type = current()/@xsi:type]) != 0">
<xsl:value-of select="concat('[',
count(preceding-sibling::*[name() = name(current()) and
@xsi:type = current()/@xsi:type]) + 1, ']')" />
</xsl:if>
</xsl:for-each>
</xsl:template>

<xsl:template match="*">
<xsl:if test="not(*)">
<!-- this element has no children, print its path -->
<xsl:apply-templates mode="path" select="." />
<xsl:text>,</xsl:text>
<xsl:value-of select="."/>
<xsl:text>&#xa;</xsl:text>
</xsl:if>
<xsl:apply-templates select="@*|*" />
</xsl:template>

<xsl:template match="@*">
<!-- for an attribute, print the path to its containing element ... -->
<xsl:apply-templates mode="path" select=".." />
<!-- ... followed by "/@attributename" -->
<xsl:value-of select="concat('/@', name(), ',', ., '&#xa;')" />
</xsl:template>
</xsl:stylesheet>

由于空节点集的字符串值是空字符串,所以做 @xsi:type = current()/@xsi:type在没有 xsi:type 的元素上是安全的并且会产生正确的结果。

您可能还想添加
<xsl:template match="@xsi:type" />

如果您不想生成类型属性的路径。

这里值得注意的是类型逻辑和计数是正交的 - 给定
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<a xsi:type="xs:string">aaa</a>
<a xsi:type="xs:integer">1</a>
<a xsi:type="xs:string">bbb</a>
<a xsi:type="xs:integer">2</a>
</root>

你会得到路径
/root/a[@xsi:type = 'xs:string'],aaa
/root/a[@xsi:type = 'xs:integer'],1
/root/a[@xsi:type = 'xs:string'][2],bbb
/root/a[@xsi:type = 'xs:integer'][2],2

每个类型的计数(这是正确的,假设正确的命名空间绑定(bind),XPath 会选择正确的东西)。

关于xml - 从 XML 文档生成 XPATH 到属性级别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19978825/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com