如何使用XSLT标记具有唯一、连续、递增整数ID的特定节点?

如何使用XSLT标记具有唯一、连续、递增整数ID的特定节点?,xslt,Xslt,我试图使用XSLT来转换文档,方法是用整数ID标记一组XML节点,从0开始,组中的每个节点增加一个。传递到样式表中的XML应该被回显,但要进行扩充以包含这些额外的信息 为了明确我所说的内容,下面是如何使用DOM表达此转换: states = document.getElementsByTagName("state"); for( i = 0; i < states.length; i++){ states.stateNum = i; } states=document.getEl

我试图使用XSLT来转换文档,方法是用整数ID标记一组XML节点,从0开始,组中的每个节点增加一个。传递到样式表中的XML应该被回显,但要进行扩充以包含这些额外的信息

为了明确我所说的内容,下面是如何使用DOM表达此转换:

states = document.getElementsByTagName("state");
for( i = 0; i < states.length; i++){
    states.stateNum = i;
}
states=document.getElementsByTagName(“state”);
对于(i=0;i
这对于DOM来说非常简单,但是我在使用XSLT时遇到了更多的麻烦。我设计的当前策略是从身份转换开始,然后创建一个全局变量,该变量选择并存储我希望编号的所有节点。然后,我创建了一个匹配这种节点的模板。这样,在模板中,我将在全局变量nodelist中查找匹配节点的位置,这将给我一个唯一的编号,然后我可以将其设置为属性

这种方法的问题是position函数只能与context节点一起使用,因此类似以下内容是非法的:

<template match="state">
    <variable name="stateId" select="@id"/>
    <variable name="uniqueStateNum" select="$globalVariable[@id = $stateId]/position()"/>
</template>

以下情况也是如此:

<template match="state">
    <variable name="stateId" select="@id"
    <variable name="stateNum" select="position($globalVariable[@id = $stateId])/"/>
</template>

我很感激任何人能给我的建议。谢谢。

最简单的方法:

<xsl:template match="s:state">
  <xsl:copy>
    <xsl:apply-templates select="@*"/>
    <xsl:attribute name="stateNum" namespace="http://msdl.cs.mcgill.ca/">
      <xsl:value-of select="count(preceding::s:state)" />
    </xsl:attribute>
    <xsl:apply-templates select="node()"/>
  </xsl:copy>
</xsl:template>


不确定XSLT处理器如何处理前面的轴,因此在任何情况下都需要对其进行基准测试。

此转换

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:s="http://www.w3.org/2005/07/scxml"
 >
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="node()|@*" name="identity">
  <xsl:copy>
    <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="s:state">
  <xsl:variable name="vNum">
   <xsl:number level="any" count="s:state"/>
  </xsl:variable>

  <xsl:copy>
   <xsl:copy-of select="@*"/>

   <xsl:attribute name="stateId">
    <xsl:value-of select="@id"/>
   </xsl:attribute>

   <xsl:attribute name="id">
     <xsl:value-of select="$vNum -1"/>
   </xsl:attribute>

   <xsl:apply-templates/>
  </xsl:copy>
 </xsl:template>
</xsl:stylesheet>
<scxml xmlns="http://www.w3.org/2005/07/scxml">
    <state id="Compound1">
        <state id="Basic1"/>
        <state id="Basic2"/>
        <state id="Basic3"/>
    </state>
</scxml>
<scxml xmlns="http://www.w3.org/2005/07/scxml">
    <state stateId="Compound1" id="0">
        <state stateId="Basic1" id="1"/>
        <state stateId="Basic2" id="2"/>
        <state stateId="Basic3" id="3"/>
    </state>
</scxml>

应用于提供的XML文档时

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:s="http://www.w3.org/2005/07/scxml"
 >
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="node()|@*" name="identity">
  <xsl:copy>
    <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="s:state">
  <xsl:variable name="vNum">
   <xsl:number level="any" count="s:state"/>
  </xsl:variable>

  <xsl:copy>
   <xsl:copy-of select="@*"/>

   <xsl:attribute name="stateId">
    <xsl:value-of select="@id"/>
   </xsl:attribute>

   <xsl:attribute name="id">
     <xsl:value-of select="$vNum -1"/>
   </xsl:attribute>

   <xsl:apply-templates/>
  </xsl:copy>
 </xsl:template>
</xsl:stylesheet>
<scxml xmlns="http://www.w3.org/2005/07/scxml">
    <state id="Compound1">
        <state id="Basic1"/>
        <state id="Basic2"/>
        <state id="Basic3"/>
    </state>
</scxml>
<scxml xmlns="http://www.w3.org/2005/07/scxml">
    <state stateId="Compound1" id="0">
        <state stateId="Basic1" id="1"/>
        <state stateId="Basic2" id="2"/>
        <state stateId="Basic3" id="3"/>
    </state>
</scxml>

生成所需的正确输出

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:s="http://www.w3.org/2005/07/scxml"
 >
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="node()|@*" name="identity">
  <xsl:copy>
    <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="s:state">
  <xsl:variable name="vNum">
   <xsl:number level="any" count="s:state"/>
  </xsl:variable>

  <xsl:copy>
   <xsl:copy-of select="@*"/>

   <xsl:attribute name="stateId">
    <xsl:value-of select="@id"/>
   </xsl:attribute>

   <xsl:attribute name="id">
     <xsl:value-of select="$vNum -1"/>
   </xsl:attribute>

   <xsl:apply-templates/>
  </xsl:copy>
 </xsl:template>
</xsl:stylesheet>
<scxml xmlns="http://www.w3.org/2005/07/scxml">
    <state id="Compound1">
        <state id="Basic1"/>
        <state id="Basic2"/>
        <state id="Basic3"/>
    </state>
</scxml>
<scxml xmlns="http://www.w3.org/2005/07/scxml">
    <state stateId="Compound1" id="0">
        <state stateId="Basic1" id="1"/>
        <state stateId="Basic2" id="2"/>
        <state stateId="Basic3" id="3"/>
    </state>
</scxml>


Tomalak,根据我对前面轴的理解,这似乎是一个合理的方法。然而,不幸的是,它似乎不起作用。请参阅以下XML文档:这将创建以下状态编号:stateId:Compound1,stateNum:0;stateId:Basic1,stateNum:0;stateId:Basic2,stateNum:1;stateId:Basic3,stateNum:2已通过Xalan、4xslt和xsltproc检查。有什么想法吗?嗯,我明白你的意思。尝试添加
count(祖先::s:state)
count(先前的::s:state)
,但这可能也是错误的。现在没有机会测试,我现在正在使用手机好问题(+1)。请参阅我的答案,以获得一个非常简单但正确的解决方案。:)