XSLT:无上下文的"生成ID"?



据我所知,xslt函数generate-id()将根据node及其上下文(祖先)返回唯一的id。

是否有一种方法来获得一个id,这只是依赖于node(及其子节点),而不是它在文档中的位置?

当使用xinclude时,相同的节点可以放置在多个位置,从而生成两个不同的id。如何为通过xinclude插入到文档中的节点集的每个实例创建相同的字母数字字符串?

我有一个文件node.xml:
<?xml version="1.0" encoding="utf-8"?>
<node name="joe"/>

和一个document.xml:

<?xml version="1.0" encoding="utf-8"?>
<document xmlns:xi="http://www.w3.org/2003/XInclude">
    <container name="first">
        <xi:include href="node.xml"/>
    </container>
    <container name="second">
        <xi:include href="node.xml"/>
    </container>
</document>

和一个process.xslt:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="container">
this will not be identical for different matches of the template, although the matched <node/> has the same content: '<xsl:value-of select="generate-id(node)"/>'
appending some attributes this is too simple, there might be differences deeper down the hierarchy, which should resolve in a different id: '<xsl:value-of select="node/@name"/>'
</xsl:template>
</xsl:stylesheet>

进程与xsltproc --xinclude process.xslt document.xml。对于<node/>的两次出现,我需要相同的id/字符串,因为它们是相同的。

的问候

啊。这看起来非常相似。但是,我不想手动连接值…?在我的情况下,它不容易扩展……也许我可以用number()来解决一些问题,但感觉应该有更多的自动功能…

ps:使用xsltproc,所以没有花哨的差异…: -)

两个节点元素不相同。它们有相同的子/属性/后代,但是它们有不同的父母和不同的兄弟姐妹。

根据深度相等函数的XPath 2.0定义,这两个节点元素可能是深度相等的。但是深度相等规范绝不是指定函数的唯一可能方式:阅读规范,你会看到任何数量的规则都可以被不同地定义。(例如,依赖于命名空间前缀、纯空白文本节点、作用域内命名空间、基本URI、类型注释)。

考虑到这些注意事项,当然在某些情况下,有一个函数说fingerprint(node),这样fingerprint(N) = fingerprint(M)当且仅当deep-equal(N, M)是有用的。您可以编写自己的函数,但它并不容易编写,而且可能效率不高。

所以它会帮助你知道为什么你认为你需要它,因为可能有一个更简单的方法来解决你的问题。

考虑以下样式表:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xi="http://www.w3.org/2003/XInclude">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>
<xsl:template match="xi:include">
    <xsl:variable name="node" select="document(@href)/*" />
    <included>
        <id>
            <xsl:value-of select="generate-id($node)"/>
        </id>
        <name>
            <xsl:value-of select="$node/@name"/>
        </name>
    </included>
</xsl:template>
</xsl:stylesheet>

当将此应用于您的输入示例时-不激活--xinclude选项-结果将是:

<?xml version="1.0" encoding="UTF-8"?>
<document xmlns:xi="http://www.w3.org/2003/XInclude">
  <container name="first">
    <included>
      <id>idp944</id>
      <name>joe</name>
    </included>
  </container>
  <container name="second">
    <included>
      <id>idp944</id>
      <name>joe</name>
    </included>
  </container>
</document>

我相信您现在尝试的方式—首先执行xinclude—会导致XSLT接收合并文档,其中每个包含实例被转换为单个节点集—处理器无法知道这些节点集曾经是一个。

相关内容

  • 没有找到相关文章

最新更新