XSLT 1.0:根据为前一个节点设置的值动态设置节点值



我正在尝试根据可能为列表中的前一个节点设置的值或可能未设置的值为节点设置值。 我需要使用 XSLT 1.0,因为这是在 IBM DataPower 设备中完成的。 还有更多的东西,但我认为这把它分解为最基本的东西。

我正在尝试识别没有前面数字范围的数字范围与重叠的数字范围。 一旦数字范围的 IsUnique 元素设置为 true,则其后面的所有其他重叠数字范围必须将其 IsUnique 元素设置为 false。

如果我有一个看起来像这样的 XML 文档:

<Range>
    <Start>1</Start>
    <End>10</End>
    <IsUnique>true</IsUnique>
</Range>
<Range>
    <Start>11</Start>
    <End>20</End>
    <IsUnique>false</IsUnique>
</Range>
<Range>
    <Start>15</Start>
    <End>21</End>
    <IsUnique>false</IsUnique>
</Range>
<Range>
    <Start>25</Start>
    <End>30</End>
    <IsUnique>false</IsUnique>
</Range>

我希望它将第二个范围内的 IsUnique 值翻转为"true",因为它的范围与之前的任何范围都不重叠。 我不希望它翻转第三个,因为它的范围与第二个重叠。 我希望它将第四个翻转为 true,因为它的范围与之前的任何范围都不重叠。 我无法弄清楚如何在处理后续节点时"看到"前一个节点的 IsUnique 值已被翻转。 这听起来很简单,我怀疑我缺少一些简单的解决方案,但我无法让它按预期工作。 我假设我需要使用 RTF 和 exsl:node-set((,但我还没有找到正确的咒语来让它工作。 谢谢!

这样怎么样?

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>
<xsl:template match="IsUnique">
    <xsl:copy>
        <xsl:value-of select="not(../../Range[generate-id()!=generate-id(current()/..) and Start &lt;= current()/../End and End >= current()/../Start])"/>
    </xsl:copy>
</xsl:template>
</xsl:stylesheet>

应用于您的(更正!(示例输入,结果为:

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <Range>
      <Start>1</Start>
      <End>10</End>
      <IsUnique>true</IsUnique>
   </Range>
   <Range>
      <Start>11</Start>
      <End>20</End>
      <IsUnique>false</IsUnique>
   </Range>
   <Range>
      <Start>15</Start>
      <End>21</End>
      <IsUnique>false</IsUnique>
   </Range>
   <Range>
      <Start>25</Start>
      <End>30</End>
      <IsUnique>true</IsUnique>
   </Range>
</root>

添加:

上面将标记与任何其他范围重叠的任何范围,无论它们之间的相对位置如何。

若要仅标记与先前区域重叠的区域(按文档顺序(,请使用:

<xsl:template match="IsUnique">
    <xsl:copy>
        <xsl:value-of select="not(../preceding-sibling::Range[Start &lt;= current()/../End and End >= current()/../Start])"/>
    </xsl:copy>
</xsl:template>

校订:

重新定义任务后,如下所示:

  1. 将每个范围标记为真或假(忽略现有标志(;

  2. 当(且仅当(一个范围与标记为 true 的先前范围重叠时,将范围标记为 false;根据此定义,第一个范围必须标记为 true。

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/root">
    <root>
        <xsl:call-template name="process-ranges">
            <xsl:with-param name="ranges" select="Range"/>
        </xsl:call-template>
    </root>
</xsl:template>
<xsl:template name="process-ranges">
    <xsl:param name="ranges"/>
    <xsl:param name="true-ranges" select="dummy-node"/>
    <xsl:param name="i" select="1"/>
    <xsl:param name="current-range" select="$ranges[$i]"/>
    <xsl:param name="unique" select="not(exsl:node-set($true-ranges)[Start &lt;= $current-range/End and End >= $current-range/Start])"/>
    <!-- output --> 
    <Range>
        <xsl:copy-of select="$current-range/Start | $current-range/End"/>
        <IsUnique>
            <xsl:value-of select="$unique"/>
        </IsUnique>
    </Range>
    <!-- recursive call -->
    <xsl:if test="$i &lt; count($ranges)">
        <xsl:call-template name="process-ranges">
            <xsl:with-param name="ranges" select="$ranges"/>
            <xsl:with-param name="true-ranges" select="$true-ranges | $current-range[$unique]"/>
            <xsl:with-param name="i" select="$i + 1"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>
</xsl:stylesheet>

结果

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <Range>
      <Start>1</Start>
      <End>10</End>
      <IsUnique>true</IsUnique>
   </Range>
   <Range>
      <Start>11</Start>
      <End>20</End>
      <IsUnique>true</IsUnique>
   </Range>
   <Range>
      <Start>15</Start>
      <End>21</End>
      <IsUnique>false</IsUnique>
   </Range>
   <Range>
      <Start>25</Start>
      <End>30</End>
      <IsUnique>true</IsUnique>
   </Range>
</root>

进一步的测试将是有序的。

相关内容

  • 没有找到相关文章