4

我有一些 XML,例如,它看起来像这样:

<root>
    <field1>test</field1>
    <f2>t2</f2>
    <f2>t3</f2>
</root>

我想用 XSLT 对其进行转换,但我想抑制输出中的第二个 f2 元素 - 如何在处理源中的第二个 f2 元素时检查我的模板内部是否已经存在输出中的 f2 元素?我的 XSLT 目前看起来像这样:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="no" omit-xml-declaration="yes" standalone="no" />
  <xsl:template match="/">
    <xsl:for-each select="./root">
      <output>
        <xsl:apply-templates />        
      </output>
    </xsl:for-each>
  </xsl:template>
  <xsl:template match="*" >
      <xsl:element name="{name(.)}">
        <xsl:value-of select="." />
      </xsl:element>
  </xsl:template>
</xsl:stylesheet>

我需要对模板中的 xsl:element 进行某种检查,但我不确定如何查询输出文档以查看该元素是否已经存在。

编辑:忘记了 pre 标签,现在应该可以看到代码了!

4

3 回答 3

7

这取决于您想要的系统范围。

即,您是否只关心同一个父级的子级元素,或同一级别的所有元素(如果您愿意,则为“表亲”)或文档中的任何元素...

在第一种情况下,您可以检查前面的兄弟轴以查看是否存在具有相同名称的任何其他元素。

<xsl:if test="count(preceding-sibling::node()[name()=name(current())])=0">
  ... do stuff in here.
</xsl:if>
于 2008-10-01T15:12:33.987 回答
1

仅检查(并警告您重复),您可以在此处找到示例

类似于以下内容:

<xsl:for-each-group select="collection(...)//@id" group-by=".">
  <xsl:if test="count(current-group()) ne 1">
    <xsl:message>Id value <xsl:value-of select="current-grouping-key()"/> is 
       duplicated in files
       <xsl:value-of select="current-group()/document-uri(/)" separator=" and
    "/></xsl:message>
  </xsl:if>
 </xsl:for-each-group>

修改为选择“根”元素内的所有节点。

至于删除重复的行,你有另一个例子here

那看起来像:

<xsl:stylesheet>
  <xsl:key name="xyz" match="record[x/y/z]" use="x/y/z" />
  <xsl:variable name="noxyzdups" select="/path/to/record[generate-id(.) = generate-id(key('xyz', x/y/z))]" />
...
  <xsl:template ... >
    <xsl:copy-of "exslt:node-set($noxyzdups)" />
  </xsl:template>
</xsl:stylesheet>

x/y/z 是您希望唯一的 xpath 表达式。它可以是 concat(x,'-',@y,'-',z) 或任何你想要的。

现在我不确定这两个示例是否可以轻松适应您的情况,但我只想指出这两个来源,以防万一。

于 2008-10-01T15:38:55.110 回答
1

无法询问转换的输出。也无法跟踪转换的当前状态(即跟踪您在变量中发出的节点)。从根本上说,这不是 XSLT 的工作方式。无副作用的编程环境的成本之一是你不能做有副作用的事情。那好吧。

在您的情况下,实现此目的的一种方法是构建一个变量,其中包含所有源元素的列表,这些源元素可以转换为您只想发出一次的输出元素。然后对照此列表检查您正在转换的每个节点。如果它不在列表中,则发出它。如果它是列表中的第一项,则发出它。否则,不要。

于 2008-10-02T00:34:06.040 回答