我有这个XML代码
<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="peptide"/>
</xsl:stylesheet>
不会改变任何事情。但是,如果最后一个路径也表示为绝对路径
<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
我想了解这背后的逻辑。
答案 0 :(得分:4)
如果匹配match =“x”的每个节点也匹配match =“/ a / b / c / x”,则将前者更改为后者的唯一效果是更改规则的优先级;该规则被认为更具体,因此具有更高的优先级,这可能导致在节点匹配多个规则时触发该规则。
答案 1 :(得分:3)
正如@Michael提到的那样,问题是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