基于条件逻辑通过XSL合并节点

时间:2012-02-10 18:40:42

标签: xslt

我有一个包含多个<item>元素的XML文档。在每个元素中,可能存在以下一个或多个元素:<list><listAfter><listBefore>。所以,忽略了很多无关的元素,它可能看起来像这样:

<items>
  <item>
    <!-- ... various elements ... -->
    <list>Enhancements</list>
  </item>
  <item>
    <!-- ... various elements ... -->
    <listBefore>Enhancements</listBefore>
    <listAfter>Bugs</listAfter>
  </item>
  <item>
    <!-- ... various elements ... -->
    <list>Enhancements</list>
    <listAfter>Next Release</listAfter>
  </item>
  <item>
    <!-- ... various elements ... -->
    <listBefore>Bugs</listBefore>
  </item>
  <item>
    <!-- ... various elements ... -->
  </item>
</items>

我想删除所有无关的<list*>元素,并且每个<list>有一个<item>元素。该元素的值应遵循以下逻辑:

  • 如果可用,请使用<list>的值。
  • 否则,请使用<listAfter>的值(如果可用)。
  • 否则,请使用<listBefore>的值(如果可用)。
  • 如果这些字段都不存在,请使用No List作为值。

使用上面的XML文档,这就是我期望输出的样子:

<items>
  <item>
    <!-- ... various elements ... -->
    <list>Enhancements</list>
  </item>
  <item>
    <!-- ... various elements ... -->
    <list>Bugs</list>
  </item>
  <item>
    <!-- ... various elements ... -->
    <list>Enhancements</list>
  </item>
  <item>
    <!-- ... various elements ... -->
    <list>Bugs</list>
  </item>
  <item>
    <!-- ... various elements ... -->
    <list>No List</list>
  </item>
</items>

除了使用Identity Transform复制所有其他元素之外,我不确定如何以一种很好的方式包含这个逻辑。一如既往,非常感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

您可以通过覆盖身份模板并添加额外的模板来匹配各种列表元素的条件来实现此目的。

要匹配 listAfter ,您希望包含在输出中,您可以执行以下操作(即 listAfter 元素,不带 list 元素作为兄弟姐妹)

<xsl:template 
   match="listAfter[not(preceding-sibling::list|following-sibling::list)]">

对于 listBefore ,只有当列表不是 listAfter 元素作为兄弟姐妹

时,才需要匹配它们
<xsl:template 
  match="listBefore[not(
    preceding-sibling::list|following-sibling::list
    |preceding-sibling::listAfter|following-sibling::listAfter)]">

在其他情况下,您会忽略 listAfter listBefore 元素:

<xsl:template match="listAfter|listBefore" />

最后,您可以将 item 元素与不同的列表元素匹配,如下所示:

<xsl:template match="item[not(list|listAfter|listBefore)]">

因此,给定以下XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes" />

   <xsl:template match="listAfter[not(preceding-sibling::list|following-sibling::list)]">
      <list>
      <xsl:apply-templates select="@*|node()"/>
      </list>
   </xsl:template>

   <xsl:template match="listBefore[not(preceding-sibling::list|following-sibling::list|preceding-sibling::listAfter|following-sibling::listAfter)]">
      <list>
      <xsl:apply-templates select="@*|node()"/>
      </list>
   </xsl:template>   

   <xsl:template match="listAfter|listBefore" />

   <xsl:template match="item[not(list|listAfter|listBefore)]">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
      <list>No List</list>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

当这个应用于您的源XML时,输出以下内容:

<items>
   <item>
      <!-- ... various elements ... -->
      <list>Enhancements</list>
   </item>
   <item>
      <!-- ... various elements ... -->
      <list>Bugs</list>
   </item>
   <item>
      <!-- ... various elements ... -->
      <list>Enhancements</list>
   </item>
   <item>
      <!-- ... various elements ... -->
      <list>Bugs</list>
   </item>
   <item>
      <!-- ... various elements ... -->
      <list>No List</list>
   </item>
</items>