XSL 1.0两个节点集的区别

时间:2013-07-09 14:05:32

标签: xslt set difference

我有一个XML文件,其结构类似于

<?xml version="1.0"?>
 <medias>
  <media>
    <id>34500</id>
    <refid/>
  </media>
  <media>
    <id>34501</id>
    <refid>34500</refid>
  </media>
  <media>
    <id>34502</id>
    <refid>34500</refid>
  </media>
  <media>
    <id>34503</id>
    <refid>34501</refid>
  </media>
 <media>
    <id>34504</id>
    <ref/>
 </media>   
 <media>
    <id>34505</id>
    <refid>34502</refid>
 </media>   
</medias>

使用XSL 1.0,我想访问其他未引用的节点。 所以我创建了两个变量

<xsl:variable name="origID" select="media/id/text()"/>
<xsl:variable name="refID" select="media/refid/text()"/>

并查看了如何在这两个元素集之间执行差异操作

<xsl:variable name="diffID" select="$origID[count(. | $refID) != count($refID)]"/>

结果是:

origID包含34500,34501,34502,34503,34504,34505

refID包含34500,34500,34501,34502

我期待

diffID将包含34503,34504,34505

但是

diffID仍包含34500,34501,34502,34503,34504,34505。

实现我的目标的最佳方法是获取ID被其他节点引用的所有节点。

提前致谢

安德烈

2 个答案:

答案 0 :(得分:1)

要将refid未引用的id转换为变量,您可以尝试这样做:

<xsl:variable name="diffID" select="media[not(id = //media/refid)]/id"/>

要证明它有效:

<xsl:template match="/*">
    <xsl:variable name="diffID" select="media[not(id = //media/refid)]/id"/>
    <xsl:for-each select="$diffID" >
        <xsl:value-of select="."/>
        <xsl:text>, </xsl:text>
    </xsl:for-each>
</xsl:template>

这将产生以下输出。

34503, 34504, 34505,

如果真实文件要大得多,则应使用xsl:key

对变量中的id做同样的事情:

<xsl:template match="/*">
    <xsl:variable name="origID" select="media/id"/>
    <xsl:variable name="refID" select="media/refid"/>
    <xsl:variable name="diffID" select="$origID[not(. = $refID)]"/>
    <xsl:for-each select="$diffID" >
        <xsl:value-of select="."/>
        <xsl:text>, </xsl:text>
    </xsl:for-each>
</xsl:template>

答案 1 :(得分:1)

使用XSLT 2.0,您可以使用except运算符(只要您选择节点而不是原始值):

<xsl:stylesheet
  version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:variable name="medias-with-id" select="//media[id]"/>
<xsl:variable name="referenced-medias" select="key('by-id', //refid)"/>

<xsl:key name="by-id" match="media" use="id"/>

<xsl:template match="/">
  <xsl:copy-of select="$medias-with-id except $referenced-medias"/>
</xsl:template>

</xsl:stylesheet>