首页 文章

模式输出中的XSLT模板包含应该在其他模式下匹配的元素

提问于
浏览
1

我想处理一些节点并再次处理这些节点的子集,特别是那些'n'祖先具有直接子'x'的节点 .

XML,尽可能简化:

<root>
        <s>
        </s>
        <s>
            <n>
                <w a="Hello"/>
                <n>
                    <x/>
                    <w a="he said"/>
                </n>
            </n>
            <n>
                <w a="how are you"/>
            </n>
        <n>
        </n>
        <n>
            <w a="she answered"/>
            <n>
                <n>
                    <x/>
                    <w a="friendly"/>
                </n>
            </n>
        </n>
    </s>
</root>

因为我必须两次处理一些w节点,所以我决定使用模式 . 我有两种模式(可读性名为'fromone','fromtwo'在这里)匹配'a-attribute',并且还尝试使用一种模式的各种组合,添加没有模式的空模板,但结果保持不变 .

XSLT的相关部分也简化了,原始模板大多与条件匹配(除了具有模式的模板):

<xsl:template match="root/s">
    <output>
        <one>
            <xsl:apply-templates select="descendant::w"/>
        </one>
        <x>
            <xsl:apply-templates select="n"/>
        </x>
    </output>
</xsl:template>

<xsl:template match="n[x]">
    <xsl:apply-templates select="descendant::w/@a" mode="fromtwo"/>
</xsl:template>

<xsl:template match="w">
    <xsl:apply-templates select="@a" mode="fromone"/>
</xsl:template>

<xsl:template match="@a" mode="fromtwo">
    <fromtwo>
        <xsl:value-of select="."/>
    </fromtwo>
</xsl:template>

<xsl:template match="@a" mode="fromone">
    <fromone>
        <xsl:value-of select="."/>
    </fromone>
</xsl:template>

我希望输出看起来像这样:

<root>
   <output>
      <one>
         <fromone>Hello</fromone>
         <fromone>he said</fromone>
         <fromone>how are you</fromone>
         <fromone>she answered</fromone>
         <fromone>friendly</fromone>
      </one>
      <x>
         <fromtwo>he said</fromtwo>
         <fromtwo>friendly</fromtwo>
      </x>
   </output>
</root>

但是在实际结果中,节点x包含我希望仅匹配来自另一个模板调用的元素到'fromone':

<x>
     <fromone>Hello</fromone>
     <fromtwo>he said</fromtwo>
     <fromone>how are you</fromone>
     <fromone>she answered</fromone>
     <fromtwo>friendly</fromtwo>
  </x>

因为这是我从我尝试的所有XSLT处理器得到的结果,我假设我的模板结构有错误 . 即使在阅读了有关模式问题的其他帖子后,我也没有更接近解决方案或在XSLT中找到我的错误 .

我犯了什么错误?

为什么结果具有两个模板的混合输出而不是仅显示'fromtwo'的输出?

2 回答

  • 0

    我犯了什么错误?

    当你这样做时:

    <x>
            <xsl:apply-templates select="n"/>
        </x>
    

    您正在将模板应用于 all n 元素 . 那些匹配 n[x] 的模板不匹配的 n 元素将由默认的built in template处理:

    <xsl:template match="*|/">
      <xsl:apply-templates/>
    </xsl:template>
    

    即它将递归地将模板应用于后代,直到它到达 w 元素 - 您有自定义模板:

    <xsl:template match="w">
        <xsl:apply-templates select="@a" mode="fromone"/>
    </xsl:template>
    

    为什么你不能简单地做:

    <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"/>
    
    <xsl:template match="root">
        <output>
            <one>
                <xsl:apply-templates select=".//w"/>
            </one>
            <x>
                <xsl:apply-templates select=".//n[x]//w" mode="fromtwo"/>
            </x>
        </output>
    </xsl:template>
    
    <xsl:template match="w">
        <fromone>
            <xsl:value-of select="@a"/>
        </fromone>
    </xsl:template>
    
    <xsl:template match="w" mode="fromtwo">
        <fromtwo>
            <xsl:value-of select="@a"/>
        </fromtwo>
    </xsl:template>
    
    </xsl:stylesheet>
    
  • 0

    这是一个默认模板的问题,它捕获每个没有 x -subelement的 n 元素 . 如果在 s -node的上下文中应用 <xsl:apply-templates select="n"/> ,则 s 的任何直接后继都不会具有 x -subnode,这样您的模板 n[x] 将永远不会匹配 . 由于没有其他模板匹配,默认模板就会到位并应用每个没有模式的子节点 .

    所以我添加了一个模板来处理所有没有 x -subelement的 n -nodes:

    <xsl:template match="n[not(x)]">
        <xsl:apply-templates select="n"/>
    </xsl:template>
    

    应用于上面的示例,它会产生以下输出:

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    
    <output xmlns="http://www.w3.org/1999/xhtml">
        <one/>
        <x/>
    </output>
    <output xmlns="http://www.w3.org/1999/xhtml">
        <one>
            <fromone>Hello</fromone>
            <fromone>he said</fromone>
            <fromone>how are you</fromone>
            <fromone>she answered</fromone>
            <fromone>friendly</fromone>
        </one>
        <x>
            <fromtwo>he said</fromtwo>
            <fromtwo>friendly</fromtwo>
        </x>
    </output>
    

相关问题