XSLT Apply模板可导出特定的父级和子级记录,子级也可以是父级

时间:2018-11-12 11:08:17

标签: xslt xslt-1.0 xslt-2.0

我的XSLT需要帮助。这是我的XML结构。

<root>
<row>
    <component>mainfield_1</component>
    <type>Field</type>
    <where_used>
        <component>subfield_2</component>
        <type>Field</type>
    </where_used>
    <where_used>
        <component>report_1</component>
        <type>Report</type>
    </where_used>
</row>
<row>
    <component>subfield_2</component>
    <type>Field</type>
    <where_used>
        <component>report_2</component>
        <type>report</type>
    </where_used>
</row>
<row>
    <component>mainfield_3</component>
    <type>Field</type>
</row>
</root>

我希望将其转换为以下内容:

<root>
<row>
    <component>mainfield_1</component>
    <type>Field</type>
</row>
<row>
    <component>subfield_2</component>
    <type>Field</type>
</row>
<row>
    <component>report_1</component>
    <type>Report</type>
</row>
<row>
    <component>report_2</component>
    <type>report</type>
</row>
</root>

基本上,我正在尝试获取组件mainfield_1的所有不同依赖项。这是我的示例代码,但这还不足以找到与子元素具有相同组件名称的任何匹配的父元素。

<xsl:template match="root">
    <root>
        <xsl:apply-templates select="row[component='mainfield_1']"/>
    </root>
</xsl:template>

<xsl:template match="row">
    <row>
        <component>
            <xsl:value-of select="component"/>
        </component>
        <type>
            <xsl:value-of select="type" />
        </type>
    </row>
    <xsl:apply-templates select="where_used"/>
</xsl:template>

<xsl:template match="where_used">
    <row>
        <component>
            <xsl:value-of select="component"/>
        </component>
        <type>
            <xsl:value-of select="type" />
        </type>
    </row>
</xsl:template>

如果我执行以上操作,将无法获得此功能。

<row>
  <component>report_2</component>
  <type>report</type>
</row>

请帮助。

1 个答案:

答案 0 :(得分:1)

考虑使用键来按row查找component

<xsl:key name="rows" match="row" use="component" />

然后,您可以有一个where_used节点的模板,这些节点引用单独的行,从而允许您选择该行

<xsl:template match="where_used[key('rows', component)]">
    <xsl:apply-templates select="key('rows', component)" />
</xsl:template>

尝试使用此XSLT

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

    <xsl:key name="rows" match="row" use="component" />

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

    <xsl:template match="root">
        <root>
            <xsl:apply-templates select="row[component='mainfield_1']"/>
        </root>
    </xsl:template>

    <xsl:template match="row">
        <row>
            <xsl:apply-templates select="* except where_used" />
        </row>
        <xsl:apply-templates select="where_used"/>
    </xsl:template>

    <xsl:template match="where_used">
        <row>
            <xsl:apply-templates />
        </row>
    </xsl:template>    

    <xsl:template match="where_used[key('rows', component)]">
        <xsl:apply-templates select="key('rows', component)" />
    </xsl:template>
</xsl:stylesheet>

请注意,我也使用了身份模板,以避免必须显式复制不需要更改的现有节点。