2011-05-04 313 views
1

说我有以下XML:基于属性,合并对节点的新模板匹配

<root> 
    <tokens> 
     <token ID="t1">blah</token> 
     <token ID="t2">blabla</token> 
     <token ID="t3">shovel</token> 
    </tokens> 

    <relatedStuff> 
     <group gID="s1"> 
     <references tokID="t1"/> 
     <references tokID="t2"/> 
     </group> 

     <group gID="s2"> 
     <references tokID="t3"/> 
     </group> 

    </relatedStuff> 
</root> 

现在,考虑到for-each循环的每一个令牌将是非常低效和a bad idea,怎么会一个去使用模板匹配,将这个XML转换为以下?

<s id="everything_merged"> 
    <tok id="t1" gID="s1" >blah</tok> 
    <tok id="t2" gID="s1" >blabla</tok> 

    <tok id="t3" gID="s2" >shovel</tok> 
</s> 

所有我从<s>要的是“GID”,对应于<tokens>令牌的GID。

<xsl:for-each select="b:root/a:tokens/a:token"> 
    <!-- and here some template matching --> 
    <xsl:attribute name="gID"> 
     <xsl:value-of select="--correspondingNode'[email protected]"/> 
    </xsl:attribute> 

</xsl:for-each> 

我对这种事很模糊,所以非常感谢您的帮助!

+0

问得好,+1。查看我的解决方案,获取完整且简短的纯“推式”解决方案,该解决方案也使用密钥。 – 2011-05-05 04:13:32

回答

2

以下样式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="/"> 
     <s id="everything_merged"> 
      <xsl:apply-templates select="/root/tokens/token" /> 
     </s> 
    </xsl:template> 
    <xsl:template match="token"> 
     <tok id="{@ID}" gID="{/root/relatedStuff/group[ 
           references[@tokID=current()/@ID]]/@gID}"> 
      <xsl:apply-templates /> 
     </tok> 
    </xsl:template> 
</xsl:stylesheet> 

应用于此输入(良好性校正):

<root> 
    <tokens> 
     <token ID="t1">blah</token> 
     <token ID="t2">blabla</token> 
     <token ID="t3">shovel</token> 
    </tokens> 
    <relatedStuff> 
     <group gID="s1"> 
      <references tokID="t1" /> 
      <references tokID="t2" /> 
     </group> 
     <group gID="s2"> 
      <references tokID="t3" /> 
     </group> 
    </relatedStuff> 
</root> 

产地:使用密钥和纯

<s id="everything_merged"> 
    <tok id="t1" gID="s1">blah</tok> 
    <tok id="t2" gID="s1">blabla</tok> 
    <tok id="t3" gID="s2">shovel</tok> 
</s> 
+0

辉煌。我不知道你可以这样做[]嵌套组[参考[@ tokID = current()/ @ ID]]!谢谢一堆! – Spectraljump 2011-05-05 12:09:00

1

的溶液“推式

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

<xsl:key name="kgIDfromTokId" match="@gID" 
    use="../*/@tokID"/> 

<xsl:template match="tokens"> 
    <s id="everything_merged"> 
    <xsl:apply-templates/> 
    </s> 
</xsl:template> 

<xsl:template match="token"> 
    <tok id="{@ID}" gID="{key('kgIDfromTokId', @ID)}"> 
    <xsl:apply-templates/> 
    </tok> 
</xsl:template> 
</xsl:stylesheet> 

时所提供的XML文档应用:

<root> 
    <tokens> 
     <token ID="t1">blah</token> 
     <token ID="t2">blabla</token> 
     <token ID="t3">shovel</token> 
    </tokens> 
    <relatedStuff> 
     <group gID="s1"> 
      <references tokID="t1" /> 
      <references tokID="t2" /> 
     </group> 
     <group gID="s2"> 
      <references tokID="t3" /> 
     </group> 
    </relatedStuff> 
</root> 

想要的,正确的结果产生

<s id="everything_merged"> 
    <tok id="t1" gID="s1">blah</tok> 
    <tok id="t2" gID="s1">blabla</tok> 
    <tok id="t3" gID="s2">shovel</tok> 
</s> 
+0

非常有用的答案,谢谢。你懂得越多!这会很有用,而且看起来更加优雅。你的方法和Lwburk之间有什么性能差异? (我应该阅读关键字和“推式”) – Spectraljump 2011-05-05 12:18:44

+0

@Twodordan:一旦执行了第一个key()函数,索引就建立了,函数的下一次执行几乎都是免费的。因此,当key()函数需要被调用至少两次时,使用键通常会更加高效。在这种情况下,它只被调用一次,我只是为了方便而使用它。这个解决方案仍然可以更高效 - 取决于特定的XSLT处理器,并且需要执行测量以找出确切的性能差异以及它是否显着。 – 2011-05-05 12:23:54