仅限XSLT apply-template到当前节点?

时间:2016-08-30 12:24:06

标签: xml xslt

是否可以将xsl:apply-templates限制为仅匹配节点,而不尝试匹配嵌套元素?

我知道我可以使用call-template。以下是我为什么要这样做的详细信息 -

我有一个由Section和Field元素组成的文档。

Section可以包含嵌套的Section元素或Field元素。字段元素没有嵌套。

例如,对于Field,模板代码的片段是:

<xsl:template match="Field" mode="Field">

    <xsl:apply-templates select="." mode="FieldHeight" />

    .....

</xsl:template>

<xsl:template match="Field[LayoutTitlePosition = 'top']" mode="FieldHeight">
    <xsl:attribute name="h" select="$glTopFieldHeight" />
</xsl:template>

<xsl:template match="Field[LayoutTitlePosition = ('left', 'right', 'none')]" mode="FieldHeight">
    <xsl:attribute name="h" select="$glHorzFieldHeight" />
</xsl:template>

使用xsl:choose / xsl:when语句可以实现同样的目的,但我发现匹配的搜索参数语法更好,更易于维护。我能够维护一个公共的Field模板,并根据输入覆盖特定的部分。由于菲尔兹没有嵌套,我不需要担心“子场”和“子场”。匹配。

我想对Section标题做同样的事情,但问题是如果我将模板应用于Section,它也可能匹配嵌套的部分。当我将模板应用于没有包含带有标题的子部分的标题的部分时会发生这种情况 - 该部分匹配两次。

编辑问题示例。

我试图创建一个最小的例子来重现这个问题。输入文件:

<?xml version="1.0" encoding="UTF-8"?>
<Root>
    <Section>
        <!-- no title -->
        <Section>
            <Title>Sub section title</Title>
            <Field>
                <Type>Text</Type>
            </Field>
        </Section>
    </Section>
</Root>

XSL转换文档:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output indent="yes" />

<xsl:template match="*" >
    <subform layout="tb">
        <xsl:apply-templates select=".[name() = 'Section']" mode="Heading" />
        <xsl:apply-templates select=".[name() = 'Field']" mode="Field" />
        <xsl:apply-templates select="*[name() = ('Section', 'Field')]" />
    </subform>
</xsl:template>

<xsl:template match="Section[Title]" mode="Heading">
    <subform layout="tb">
        <xsl:call-template name="drawHeading" />
    </subform>
</xsl:template>

<xsl:template name="drawHeading">
    <Heading><xsl:value-of select="Title" /></Heading>
</xsl:template>

<xsl:template match="Field" mode="Field">
    <field name="{@Name}">
    </field>
</xsl:template>

输出,来自转换输入文档:

<?xml version="1.0" encoding="UTF-8"?>
<subform layout="tb">
    <subform layout="tb">
        <subform layout="tb">
            <Heading>Sub section title</Heading>
        </subform>
        <subform layout="tb">
            <subform layout="tb">
                <Heading>Sub section title</Heading>
            </subform>
            <subform layout="tb">
                <field name=""/>
            </subform>
        </subform>
    </subform>
</subform>

当没有标题的父节不匹配时,似乎子节标题匹配。

我想要达到的结果是:

<?xml version="1.0" encoding="UTF-8"?>
<subform layout="tb">
    <subform layout="tb">

        <subform layout="tb">
            <subform layout="tb">
                <Heading>Sub section title</Heading>
            </subform>
            <subform layout="tb">
                <field name=""/>
            </subform>
        </subform>
    </subform>
</subform>

如果标题出现在源文档中,例如:

<?xml version="1.0" encoding="UTF-8"?>
<Root>
    <Section>
        <Title>Section title</Title>
        <Section>
            <Title>Sub section title</Title>
            <Field>
                <Type>Text</Type>
            </Field>
        </Section>
    </Section>
</Root>

然后它应该产生:

<?xml version="1.0" encoding="UTF-8"?>
<subform layout="tb">
    <subform layout="tb">
        <subform layout="tb">
            <Heading>Section title</Heading>
        </subform>
        <subform layout="tb">
            <subform layout="tb">
                <Heading>Sub section title</Heading>
            </subform>
            <subform layout="tb">
                <field name=""/>
            </subform>
       </subform>
   </subform>
</subform>

1 个答案:

答案 0 :(得分:1)

似乎只需使用FieldTitle的两个专用模板即可:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output indent="yes" />

<xsl:template match="*" >
    <subform layout="tb">
        <xsl:apply-templates/>
    </subform>
</xsl:template>


<xsl:template match="Title">
    <subform layout="tb">
        <Heading><xsl:value-of select="." /></Heading>
    </subform>
</xsl:template>

<xsl:template match="Field">
    <subform layout="tb">
       <field name="{@Name}"></field> 
    </subform>
</xsl:template>

</xsl:stylesheet>

http://xsltransform.net/pPJ8LUX在线。