如何概括XSL Transformation文件以用于所有场景

时间:2012-04-24 11:23:12

标签: xml xslt

如果我有这个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. 如果它是之前删除所有节点的最后一个节点,则保留“stop
  2. 如果带有'stop'方法的节点不是最后一个节点,则用'stop'删除该节点,然后删除该节点之前的所有节点(在该停止之后离开所有节点)。
  3. 必须在父母的id属性相同的孩子中发生,并且只删除子节点(即使删除了用户节点后父母也是空的)。< / p>

    对于上面的示例:

    1. item id = 0暂停然后item id = 0 stop - &gt;结果将是 item id = 0 stop (parent:Items id = a_1-pause)。
    2. person id = b_1a start然后person id = b_1a pause然后person id = b1_a stop(parent:person id = b_1) - 所以结果变为 only person id = b_1a stop
    3. person id = b_1b pause然后person id = b_1b stop然后person id = b_1b start然后person id = b_1b pause - &gt;它会变成 person id = b_1b start然后person id = b_1b pause (我们再次比较父亲Person id = b_1下的每个人;在父母中我们不关心其中一个人是否有方法只要它与示例中显示的id相同)
    4. 这就是我只为'人'节点所拥有的。

      <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>
      

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

      亲切的问候, 约翰

1 个答案:

答案 0 :(得分:0)

  

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

我猜这意味着你之前提到的约束只适用于兄弟节点。但是你的id =“0”的例子表明这不是真的。所以我想我不明白上面的条款。

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

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

如果最后出现一个带'stop'方法的元素,那么将删除具有相同用户ID的其他方法(例如'pause'和'run')的任何其他节点。但是如果一个带有'stop'方法的元素不是最后一个,那么带有'stop'的元素和那个'stop'之前的所有元素(具有相同的id?)将会被删除。

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

如果有一个带有'stop'方法的元素,那么该元素以及具有相同元素名称和相同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>

我有点难以理解您对算法的规范,因此如果上述方法无法产生预期结果,请举一个具体示例,说明其结果与预期结果的不同之处,并阐明规范。

更新:我已根据最近的评论稍微更新了上述代码,但现在还没有完全符合我现在所理解的规范。今晚我会努力研究它。 (其他人也欢迎拍摄!)