根据我的理解,xslt函数generate-id()
将返回一个唯一的id,具体取决于node
及其上下文(祖先)。
有没有办法获得一个只依赖于node
(和它的子节点)的id,而不是它在文档中的位置?
使用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 /字符串,因为它们是相同的。
问候
哎呀。 this看起来非常相似。但是,我不想手动连接值......?在我的情况下它不容易扩展......也许我可以使用number()
来解决问题,但感觉应该有更多自动...
ps:使用xsltproc,所以没有花哨的声音......; - )
答案 0 :(得分:1)
两个节点元素不相同。他们有相同的孩子/属性/后代,但他们有不同的父母和不同的兄弟姐妹。
根据深度相等函数的XPath 2.0定义,两个节点元素可能深度相等。但是,深度相等的规范绝不是指定函数的唯一可能方式:阅读规范,您将看到可以以不同方式定义任意数量的规则。 (例如,对名称空间前缀的依赖性,仅空白文本节点,范围内名称空间,基本URI,类型注释)。
鉴于这些警告,有些情况下,如果fingerprint(node)
函数fingerprint(N) = fingerprint(M)
deep-equal(N, M)
,www.site.com/api
当前和仅api.site.com
。你可以编写自己的函数,但编写起来并不容易,而且效率可能不高。
因此,有必要了解您认为自己需要它的原因,因为可能有更简单的方法来解决您的问题。
答案 1 :(得分:0)
考虑以下样式表:
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接收合并文档,其中每个包含实例被转换为单个节点集 - 并且处理器无法处理知道这些节点集曾经是一个。