1

如果我有这个 xml 文件:

    <root> 
    <node id="a">
        <Items id="a_1" method="pause">
            <item id="0" method="pause">
                <attribute>
                    <color>Red</color>
                </attribute>
            </item>
        </Items>

        <Items id="a_1" method="pause">
            <item id="0" method="stop">
                <attribute>
                    <color>Red</color>
                </attribute>
            </item>
        </Items>            
    </node>

    <node id="b">
        <Persons id="b_1">    
            <person id="b_1b" method="pause">
                <attribute>a</attribute>
            </person>       
            <person id="b_1a" method="start">
                <attribute>
                    <name>John</name>
                </attribute>
            </person>
            <person id="b_1b" method="stop">
                <attribute>a</attribute>
            </person>
            <person id="b_1a" method="pause">
                <attribute>a</attribute>
            </person>
        </Persons>

        <Persons id="b_1" method="start">               
            <person id="b_1a" method="stop">
                <attribute>a</attribute>
            </person>

            <person id="b_1b" method="start">
                <attribute>a</attribute>
            </person>
            <person id="b_1b" method="pause">
                <attribute>a</attribute>
            </person>
        </Persons>

        <Persons id="b_2">                
            <person id="b_1a" method="start">
                <attribute>
                    <name>John</name>
                </attribute>
            </person>
        </Persons>
    </node>
</root>

预期的输出是:

    <root> 
    <node id="a">
        <Items id="a_1" method="pause">

        </Items>

        <Items id="a_1" method="pause">
            <item id="0" method="stop">
                <attribute>
                    <color>Red</color>
                </attribute>
            </item>
        </Items>            
    </node>

    <node id="b">
        <Persons id="b_1">    
        </Persons>

        <Persons id="b_1" method="start">               
            <person id="b_1a" method="stop">
                <attribute>a</attribute>
            </person>

            <person id="b_1b" method="start">
                <attribute>a</attribute>
            </person>
            <person id="b_1b" method="pause">
                <attribute>a</attribute>
            </person>
        </Persons>

        <Persons id="b_2">                
            <person id="b_1a" method="start">
                <attribute>
                    <name>John</name>
                </attribute>
            </person>
        </Persons>
    </node>
</root>

该算法的关键在于停止方法。

  1. 如果它是最后一个删除所有节点并留下一个'停止
  2. 如果具有“停止”方法的节点不是最后一个,则删除具有“停止”的该节点及其之前的所有节点(在该停止之后保留所有节点)。

这必须发生在父母的id属性相同的孩子中,它只会删除子节点(删除用户节点后即使它是空的也离开父母)。

对于上面的例子:

  1. item id=0 pause 然后 item id=0 stop -> 结果将是item id=0 stop(父项:Items id=a_1-pause)。
  2. 人 id=b_1a 开始然后人 id=b_1a 暂停然后人 id=b1_a 停止(父母:人 id=b_1) - 所以结果变成只有人 id=b_1a 停止
  3. person id=b_1b pause 然后 person id=b_1b stop 然后 person id=b_1b start 然后 person id=b_1b pause -> 它将变成person id=b_1b start 然后 person id=b_1b pause(我们再次比较父 Person id 下的每个人=b_1; 在父级中,我们不关心其中一个是否没有方法,只要它与示例中所示的 id 相同)

这就是我只为“人”节点所拥有的。

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

   <!-- Ignore person with 'stop' method which are not the last such person -->
   <xsl:template match="person[@method='stop'][following::person[@method='stop']]"/>

   <!-- Match other persons -->
   <xsl:template match="person">
      <!-- Copy the person if there isn't a following person with the same id and 'stop' method -->
      <xsl:if test="not(following::person[@id=current()/@id][@method='stop'])">
         <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
         </xsl:copy>
      </xsl:if>
   </xsl:template>

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

是否可以更改以解决所有其他节点(节点和父名称可以是任何东西)?非常感谢。

亲切的问候,约翰

4

1 回答 1

0

这必须发生在同一个父母身上

我猜这意味着您之前提到的约束仅适用于兄弟节点。但是,您的 id="0" 示例表明这不是真的。所以我想我不明白上面的条款。

更新:这并不意味着“在一个父元素的子元素中”,而是“在其父元素的 id 属性具有相同值的元素中”。

到目前为止我对规范的理解:

如果具有“停止”方法的元素最后出现,则具有相同用户标识的具有其他方法(例如“暂停”和“运行”)的任何其他节点将被删除。但是,如果具有“停止”方法的元素不是最后一个,则具有“停止”的元素本身以及该“停止”之前的所有元素(具有相同的 id?)都将被删除。

在我看来,这可以概括为:

如果存在具有“停止”方法的元素,则该元素以及具有相同元素名称和相同 id 属性的任何先前元素将被删除。

如果此摘要不正确,请澄清。

是否可以更改以解决所有其他节点(节点和父名称可以是任何东西)?

我还没有想到一种方法可以仅通过模板匹配来做到这一点。但它可以像你一样在 xsl:if 中完成:

<xsl:template match="*">
  <!-- Copy the element if there isn't a following sibling element with
       the same name, same id and 'stop' method, and if the element itself
       doesn't have a 'stop' method. -->
  <xsl:if test="not(@method = 'stop' or
                    following::*[local-name() = local-name(current()) and
                      @id = current()/@id and
                      ../@id = current()/../@id and
                      @method = 'stop'])">
     <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
     </xsl:copy>
  </xsl:if>
</xsl:template>

我有点难以理解您对算法的规范,所以如果上述内容没有产生预期的结果,请给出一个具体示例,说明其结果与预期结果不同的地方,并澄清规范。

更新:我已经根据最近的评论更新了上面的代码,但它还没有完全符合我现在理解的规范。今晚我会努力解决这个问题。(也欢迎其他人来拍!)

于 2012-04-24T14:23:19.813 回答