如何使用当前节点获取最短的XML子树?

时间:2014-07-18 09:03:46

标签: xslt-1.0

我有类似的东西:

<XML>
    <LEVEL1A>
        <LEVEL2AA>
            <LEVEL3AAA>Some textAAA</LEVEL3AAA>
        </LEVEL2AA>
        <LEVEL2AB>Some textAB</LEVEL2AB>
    </LEVEL1A>
    <LEVEL1B>
        <LEVEL2BA>Some textBA</LEVEL2BA>
    </LEVEL1B>
    <LEVEL1C>
        <LEVEL2CA>
            <LEVEL3CAA>Some textCAA</LEVEL3CAA>
            <LEVEL3CAB>Some textCAB</LEVEL3CAB>
        </LEVEL2CA>
        <LEVEL2CB>Some textCB</LEVEL2CB>
        <LEVEL2CC>Some textCC</LEVEL2CC>
    </LEVEL1C>
</XML>

如果我需要将所有父节点作为节点//XML/LEVEL1C/LEVEL2CA/LEVEL3CAB的XML树,那么应该接收结果:

<XML>
    <LEVEL1C>
        <LEVEL2CA>
            <LEVEL3CAB>Some textCAB</LEVEL3CAB>
        </LEVEL2CA>
    </LEVEL1C>
</XML>

所以,我不需要得到父母的名字,但我需要整个子树。

如果我有点//XML/LEVEL1C/LEVEL2CA/LEVEL3CAB//XML/LEVEL1A/LEVEL2AA/LEVEL3AAA到节点树,那么我必须收到:

<XML>
    <LEVEL1A>
        <LEVEL2AA>
            <LEVEL3AAA>Some textAAA</LEVEL3AAA>
        </LEVEL2AA>
    </LEVEL1A>
    <LEVEL1C>
        <LEVEL2CA>
            <LEVEL3CAB>Some textCAB</LEVEL3CAB>
        </LEVEL2CA>
    </LEVEL1C>
</XML>

有办法吗?

UPD: 我有for-each循环,最后我返回<xsl:copy-of select="$output-node"/>它是命名模板的一部分,当这个命名模板被调用时,$ output-node为<xsl:with-param name="output-node" select="//XML/LEVEL1A/LEVEL2CA/LEVEL3CAB"/>

但是现在我不仅需要打印该节点,还要打印该节点和该节点的最短XML子树。

UPD2: 这是解析它的xslt示例:

<xsl:template name="printme">
    <xsl:param name="output-node"/>
                <CURRENT_NODE>
                    <xsl:copy-of select="$output-node"/>
                </CURRENT_NODE>
</xsl:template> 

<xsl:for-each select="//XML">

    <xsl:if test="//current()/text() = 'Some textCAB'">

        <xsl:call-template name="comparefunc">
            <xsl:with-param name="output-node" select="//current()"/> 
        </xsl:call-template>    
    </xsl:if>    
</xsl:for-each>

现在我需要CURRENT_NODE而不仅仅是<LEVEL3CAB>Some textCAB</LEVEL3CAB>,而是整个:

<CURRENT_NODE>
    <XML>
        <LEVEL1C>
            <LEVEL2CA>
                <LEVEL3CAB>Some textCAB</LEVEL3CAB>
            </LEVEL2CA>
        </LEVEL1C>
    </XML>
</CURRENT_NODE>

1 个答案:

答案 0 :(得分:2)

为简单起见,让我将您的输入示例调整为:

<XML>
    <LEVEL1A>
        <LEVEL2AA>
            <LEVEL3AAA>error</LEVEL3AAA>
        </LEVEL2AA>
        <LEVEL2AB>ok</LEVEL2AB>
    </LEVEL1A>
    <LEVEL1B>
        <LEVEL2BA>ok</LEVEL2BA>
    </LEVEL1B>
    <LEVEL1C>
        <LEVEL2CA>
            <LEVEL3CAA>ok</LEVEL3CAA>
            <LEVEL3CAB>error</LEVEL3CAB>
        </LEVEL2CA>
        <LEVEL2CB>ok</LEVEL2CB>
        <LEVEL2CC>ok</LEVEL2CC>
    </LEVEL1C>
</XML>

在这个例子中,我们对包含文本&#34;错误&#34;的元素感兴趣。第一步将创建一个变量,其中包含通过此测试的所有元素的节点集。然后我们将遍历整棵树,只留下这些元素及其祖先:

XSLT 1.0

<?xml version="1.0" encoding="UTF-8"?>
<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" />

<!-- 1. identify nodes of interest  -->
<xsl:variable name="errors" select="//*[.='error']" />

<!-- 2. traverse the entire tree, leaving only nodes of interest and their ancestors -->
<xsl:template match="*">
    <xsl:choose>
        <xsl:when test="descendant::*[count(.|$errors) = count($errors)]">
        <!-- at least one of the descendants is a member of $errors -->
            <xsl:copy>
                <xsl:apply-templates select="*"/>
            </xsl:copy>
        </xsl:when>
        <xsl:when test="count(.|$errors) = count($errors)">
        <!-- this element is a member of $errors -->
            <xsl:copy-of select="."/>
        </xsl:when>
    </xsl:choose>
</xsl:template>

</xsl:stylesheet>

当应用于我们的示例输入时,结果将是:

<?xml version="1.0" encoding="UTF-8"?>
<XML>
   <LEVEL1A>
      <LEVEL2AA>
         <LEVEL3AAA>error</LEVEL3AAA>
      </LEVEL2AA>
   </LEVEL1A>
   <LEVEL1C>
      <LEVEL2CA>
         <LEVEL3CAB>error</LEVEL3CAB>
      </LEVEL2CA>
   </LEVEL1C>
</XML>
相关问题