【问题标题】:Filter Tree using XSLT使用 XSLT 过滤树
【发布时间】:2013-05-23 02:04:45
【问题描述】:

我有像这样 final.xml 的树结构的 xml 文件

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="b.xsl"?> 
<childrens>
<child_1 entity_id="1" value="Root Catalog" parent_id="0">
    <child_2 entity_id="2" value="Navigate" parent_id="1">
        <child_4 entity_id="4" value="Activities" parent_id="2">
            <child_10066 entity_id="10066" value="Physical1" parent_id="4">
                <child_10067 entity_id="10067" value="Cricket" parent_id="10066">
                    <child_10068 entity_id="10068" value="One Day" parent_id="10067"/>
                </child_10067>
            </child_10066>
            <child_10069 entity_id="10069" value="Test2" parent_id="4"/>
            <child_10070 entity_id="10070" value="Test3" parent_id="4"/>
            <child_10071 entity_id="10071" value="Test4" parent_id="4"/>
            <child_10072 entity_id="10072" value="Test5" parent_id="4"/>
            <child_5 entity_id="5" value="Physical" parent_id="4"/>
        </child_4>
        <child_4331 entity_id="4331" value="Region" parent_id="2">
            .
            .
            .
            .
        </child_4331>
    </child_2>
</child_1>
</childrens>

这是我的 xslt 代码

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

  <xsl:template match="*" mode="item">
        <li>
          <xsl:value-of select="@value"/>
          <xsl:apply-templates select="current()[*]"/>
        </li>
 </xsl:template>

  <xsl:template match="*/*/*">
    <ul>
      <xsl:apply-templates select="*[1] | node()[current()/ancestor::*[3]]" mode="item"/>
     <xsl:if test="local-name(child::*) = 'child_4'"><div id="Activity"></div></xsl:if>
    </ul>
  </xsl:template>
</xsl:stylesheet>

我还有另一个 xml 文件,其中包含叶节点的 id 我只想显示filter.xml 文件中的那些节点(及其父 id)

filter.xml 是

<products>
  <product_id value="1">
    <tab_id value="351">
      <tab_name value="test1"/>
      <dist_activity value="5"/>
      <dist_activity value="10068"/>
      <dist_activity value="10070"/>
    </tab_id>
  </product_id>
  <product_id value="2">
    <tab_id value="352">
      <tab_name value="test2"/>
      <dist_activity value="10069"/>
    </tab_id>
  </product_id>
</products>

这里 dist_activity 包含叶节点的 id,它是主 xml 文件中的 entity_id,所以我想使用这 2 个 xml 文件进行输出。目前我只使用主 xml 文件而不是 filter.xml 文件这是我当前的输出和我想要同时使用这两个文件的输出

这是在 filter.xml 中的 One day(10068),Test2(10069),test3(10070),Physical(5) 所以我只想要我树中的那些

那么我需要在我的xslt 代码中做哪些更改???

【问题讨论】:

    标签: xml xslt xpath


    【解决方案1】:

    过滤器应该如何工作并不完全清楚(对我来说)。从您的声明中:
    这里在 filter.xml 中有一天 (10068)、Test2(10069)、test3(10070)、Physical(5),所以我只想要我树中的那些 和我期望的filter.xml: 您希望在您的输出中为 child_xxxx 元素添加 li 元素,其中 self 的 entity_id 或后代作为 filter.xml 中 dist_activity 的 @value 存在。

    因此尝试对您的 xlst 进行这个小改动:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output method="html" indent="yes" omit-xml-declaration="yes"/>
    
        <xsl:variable name="filter" select="document('iz1_filter.xml')"/>
    
        <xsl:template match="*" mode="item">
            <xsl:if test="$filter//dist_activity[@value= current()/descendant-or-self::*/@entity_id ]" >
                <li>
                    <xsl:value-of select="@value"/>
                    <xsl:apply-templates select="current()[*]"/>
                </li>
            </xsl:if>
        </xsl:template>
    
        <xsl:template match="*/*/*">
            <ul>
                <xsl:apply-templates select="*[1] | node()[current()/ancestor::*[3]]" mode="item"/>
                <xsl:if test="local-name(child::*) = 'child_4'">
                    <div id="Activity"></div>
                </xsl:if>
            </ul>
        </xsl:template>
    </xsl:stylesheet>
    

    这将生成以下输出:

    <ul>
        <li>
            Activities<ul>
                <li>
                    Physical1<ul>
                        <li>
                            Cricket<ul>
                                <li>One Day</li>
                            </ul>
                        </li>
                    </ul>
                </li>
                <li>Test2</li>
                <li>Test3</li>
                <li>Physical</li>
            </ul>
        </li>
        <div id="Activity"></div>
    </ul>
    

    【讨论】:

      【解决方案2】:

      node()[current()/ancestor::*[3]] 选择具有至少三个祖先的所有子节点。由于当前节点有两个父节点,因此它的所有子节点都具有三个祖先节点。

      如果您想选择只有三个先前兄弟姐妹的,请尝试使用 preceding-sibling 轴,而不是 ancestor 轴。

      【讨论】:

      • 我要输出 usnig filter.xml
      • 这就是你真正想要的吗?如果你只想要前三项,为什么不select="node()[position() &lt; 4]"
      猜你喜欢
      • 1970-01-01
      • 2014-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多