2011-12-13 43 views
1

我有这样的XML代码XSLT相对或绝对路径,意外行为

<data> 

<proteins> 
<protein> 
<accession>111</accession> 
</protein> 
</proteins> 

<peptides> 
<peptide> 
<accession>111</accession> 
<sequence>AAA</sequence> 
</peptide> 
<peptide> 
<accession>111</accession> 
<sequence>AAA</sequence> 
</peptide> 
<peptide> 
<accession>111</accession> 
<sequence>AAA</sequence> 
</peptide> 
<peptide> 
<accession>111</accession> 
<sequence>BBB</sequence> 
</peptide> 
<peptide> 
<accession>111</accession> 
<sequence>BBB</sequence> 
</peptide> 
<peptide> 
<accession>111</accession> 
<sequence>BBB</sequence> 
</peptide> 
<peptide> 
<accession>111</accession> 
<sequence>BBB</sequence> 
</peptide> 
</peptides> 

</data> 

和这个XSLT代码

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/> 
    <xsl:key name="byAccSeq" match="peptide" 
          use="concat(accession, '|', sequence)"/> 
    <xsl:template match="/"> 
     <root><xsl:apply-templates select="/*/proteins/protein"/></root> 
    </xsl:template> 
    <xsl:template match="protein"> 
     <xsl:apply-templates 
      select="../../peptides/peptide[accession=current()/accession]"/> 
    </xsl:template> 
    <xsl:template match="peptide[generate-id()= 
      generate-id(key('byAccSeq', concat(accession, '|', sequence))[1])]"> 
     <xsl:copy-of select="."/> 
    </xsl:template> 
    <xsl:template match="peptide"/> 
</xsl:stylesheet> 

的输出是这一个

<root> 
    <peptide> 
     <accession>111</accession> 
     <sequence>AAA</sequence> 
    </peptide> 
    <peptide> 
     <accession>111</accession> 
     <sequence>BBB</sequence> 
    </peptide> 
</root> 

现在,同样XSLT代码,但几乎所有路径都改为绝对路径

​​

不会改变任何东西。然而,如果最后路径也表示为绝对

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/> 
    <xsl:key name="byAccSeq" match="/data/peptides/peptide" 
          use="concat(accession, '|', sequence)"/> 
    <xsl:template match="/"> 
     <root><xsl:apply-templates select="/data/proteins/protein"/></root> 
    </xsl:template> 
    <xsl:template match="/data/proteins/protein"> 
     <xsl:apply-templates 
    select="/data/peptides/peptide[accession=current()/accession]"/> 
    </xsl:template> 
    <xsl:template match="/data/peptides/peptide[generate-id()= 
      generate-id(key('byAccSeq', concat(accession, '|', sequence))[1])]"> 
     <xsl:copy-of select="."/> 
    </xsl:template> 
    <xsl:template match="/data/peptides/peptide"/> 
</xsl:stylesheet> 

那么输出中简直是

<root></root> 

我没有想到这一点。

而且,还意外地(对我来说),如果我之前写的模板匹配,输出再次是希望一个

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/> 
    <xsl:key name="byAccSeq" match="/data/peptides/peptide" 
          use="concat(accession, '|', sequence)"/> 
    <xsl:template match="/"> 
     <root><xsl:apply-templates select="/data/proteins/protein"/></root> 
    </xsl:template> 
    <xsl:template match="/data/proteins/protein"> 
     <xsl:apply-templates 
    select="/data/peptides/peptide[accession=current()/accession]"/> 
    </xsl:template> 
    <xsl:template match="/data/peptides/peptide"/> 
    <xsl:template match="/data/peptides/peptide[generate-id()= 
      generate-id(key('byAccSeq', concat(accession, '|', sequence))[1])]"> 
     <xsl:copy-of select="."/> 
    </xsl:template> 
</xsl:stylesheet> 

最后文件:http://www.xsltcake.com/slices/sgWUFu

我想,了解逻辑在这之后。

回答

2

作为@迈克尔提到的问题是template conflict resolution之一。将匹配模式从peptide更改为/data/peptides/peptide会将模板的优先级提高到与处理/data/peptides/peptide[generate-id()= generate-id(key('byAccSeq', concat(accession, '|', sequence))[1])]的模板相同的级别。文档中有一些节点可以通过这两种匹配模式进行选择,这会导致模板冲突。

这在技术上是有不止一个匹配的模板规则的错误,但处理器通常由文档,这就是为什么改变模板的顺序产生不同的结果,在将最后一个匹配模板恢复。

正如迈克尔会清楚地知道,撒克逊产生以下警告:

Recoverable error 
    XTRE0540: Ambiguous rule match for /data/peptides[1]/peptide[1] 
Matches both "/data/peptides/peptide" on line 16 of file:///C:/sandbox/so.xsl 
and "/data/peptides/peptide[generate-id()= generate-id(key('byAccSeq', concat(accession, 
    '|', sequence))[1])]" on line 13 of file:///C:/sandbox/so.xsl 
Recoverable error 
    XTRE0540: Ambiguous rule match for /data/peptides[1]/peptide[4] 
Matches both "/data/peptides/peptide" on line 16 of file:///C:/sandbox/so.xsl 
and "/data/peptides/peptide[generate-id()= generate-id(key('byAccSeq', concat(accession, 
    '|', sequence))[1])]" on line 13 of file:///C:/sandbox/so.xsl 
+0

然后,如果它应被视为一个错误,是有其他选择吗?或者换句话说,处理器的行为在确定哪个规则适用时是健壮的? – Gerard 2011-12-13 21:49:39

2

如果每个匹配匹配=“X”也匹配匹配节点=“/ A/B/C/X”,然后改变前者向后者的唯一作用是改变规则的优先级;该规则被认为是更具体的,因此具有更高的优先级,当节点匹配多个规则时可能导致该规则被触发。