从包含特定节点的当前位置查找项目

时间:2014-05-02 11:41:17

标签: xslt

我需要解析由嵌套组中的组件组成的xml。结果将是js数组。我希望只有在嵌套级别中有一个组件才能创建组。 我可以搜索节点是否包含以下方法的组件:

<xsl:if test="count(.//ModuleComponent) > 0">

只有当前位置的其他所有节点都有组件时,才需要在数组元素之间加上逗号。这是我不能做的。如果它们有组件,我需要在当前所有节点内搜索。

这条线仅适用于下一个兄弟,而不是全部。

    <xsl:if test="count(following-sibling::ModuleComponent) > 0">

我的样本是:

<xsl:text>[</xsl:text>
<!--create components of group-->
<xsl:for-each select="Module/Groups/Group">
    <xsl:call-template name="GroupTemplate">
    </xsl:call-template>
</xsl:for-each>
<xsl:text>]</xsl:text>


<xsl:template name="GroupTemplate">
    <xsl:variable name="groupID" select="@ID"/>
    <!-- create this group only if it has components deep inside -->
    <xsl:if test="count(.//ModuleComponent) > 0">
        {
            id: <xsl:value-of select="$ID" />
            ...
            group body
            ...
        }
        <xsl:if test="count(following-sibling::ModuleComponent) > 0"><xsl:text>,</xsl:text></xsl:if>
    </xsl:if>
</xsl:template>

和示例xml是:

<Module>
    <Groups>
        <Group ID="1">
            <Groups>
                <Group ID="11">
                    <Component ID="c1"/>
                </Group>
            </Groups>
        </Group>
        <Group ID="2">
            <Groups>
                <Group ID="22">
                </Group>
            </Groups>
        </Group>
        <Group ID="3">
            <Groups>
                <Group ID="33">
                    <Component ID="c3"/>
                </Group>
            </Groups>
        </Group>
    </Groups>
</Module>

感谢任何想法或帮助。

2 个答案:

答案 0 :(得分:1)

将其设为匹配模板而不是被调用模板,并将“我是否包含任何ModuleComponent”逻辑移动到谓词而不是if

<xsl:text>[</xsl:text>
<xsl:apply-templates select="Module/Groups/Group[.//ModuleComponent]"/>
<xsl:text>]</xsl:text>

<xsl:template match="Group">
  <xsl:if test="position() &gt; 1">,</xsl:if>
  {
        id: <xsl:value-of select="@id" />
        ...
        group body
        ...
  }
</xsl:template>

现在,您仅对至少包含一个组件的群组进行操作,而position()列表中<{1}}的位置而不是列表中的位置所有组,所以你只需在除第一个之前的所有组之前添加一个逗号。

答案 1 :(得分:0)

如果要生成数组,则不必调用单独的模板。您可以将第一个for-each更改为.//Component上的迭代并测试last()位置:

<xsl:text>[</xsl:text>
<xsl:for-each select=".//Component">
    {
    id: <xsl:value-of select="@ID" />
    ...
    component body
    ...
    }
    <xsl:if test="not(position() = last())"><xsl:text>,</xsl:text></xsl:if>
</xsl:for-each>
<xsl:text>]</xsl:text>