Xslt 基于属性对多个同级重新排序

Xslt 基于属性对多个同级重新排序,xslt,Xslt,我想生成一个HTML文件,如以下示例所示: 英语 这是一位伟大的精英 努克·鲁特鲁姆,爱神坐在阿梅特·奥纳雷·福西布斯身边 法国 神父Lorem ipsum dolor sit amet,献祭精英 努克·鲁特鲁姆,爱神坐在阿梅特·奥纳雷·福西布斯身边 来自以下示例XML源,对此我没有控制权: <?xml version="1.0" encoding="ISO-8859-1"?> <content id=""> <header language="en"&g

我想生成一个HTML文件,如以下示例所示:

英语

这是一位伟大的精英

努克·鲁特鲁姆,爱神坐在阿梅特·奥纳雷·福西布斯身边

法国 神父Lorem ipsum dolor sit amet,献祭精英

努克·鲁特鲁姆,爱神坐在阿梅特·奥纳雷·福西布斯身边

来自以下示例XML源,对此我没有控制权:

<?xml version="1.0" encoding="ISO-8859-1"?>
<content id="">
    <header language="en">
        <enabled>true</enabled>
        <img src="http://i.stack.imgur.com/xGCNw.gif" />
        <!-- more header-related elements -->
    </header>
    <header language="fr">
        <enabled>false</enabled>
        <img src="" />
        <!-- more header-related elements -->
    </header>
    <html language="en" type="source">
    <![CDATA[
        <p>En Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
        <p>Nunc rutrum, eros sit amet ornare faucibus.</p>
        ]]>
    </html>
    <html language="fr" type="source">
    <![CDATA[
        <p>Fr Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
        <p>Nunc rutrum, eros sit amet ornare faucibus.</p>
        ]]>
    </html>
</content>

真的
假的
这是一位伟大的精英

努克·鲁特鲁姆,爱神坐在阿梅特·奥纳雷·福西布斯身边

]]> 神父Lorem ipsum dolor sit amet,献祭精英

努克·鲁特鲁姆,爱神坐在阿梅特·奥纳雷·福西布斯身边

]]>
所以我写了这个XSLT来实现这一点:

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

    <xsl:template match="/">
        <h1>English</h1>
        <hr/>
        <xsl:for-each select="content/header">
            <xsl:call-template name="header">
                <xsl:with-param name="lang">en</xsl:with-param>
            </xsl:call-template>
        </xsl:for-each>
        <xsl:for-each select="content/html">
            <xsl:call-template name="html">
                <xsl:with-param name="lang">en</xsl:with-param>
            </xsl:call-template>
        </xsl:for-each>
        <hr/>
        <h1>Français</h1>
        <hr/>
        <xsl:for-each select="content/header">
            <xsl:call-template name="header">
                <xsl:with-param name="lang">fr</xsl:with-param>
            </xsl:call-template>
        </xsl:for-each>
        <xsl:for-each select="content/html">
            <xsl:call-template name="html">
                <xsl:with-param name="lang">fr</xsl:with-param>
            </xsl:call-template>
        </xsl:for-each>
    </xsl:template>

    <xsl:template name="header" match="*">
        <xsl:param name='lang'/>
        <xsl:if test="current()[@language=$lang]">
            <xsl:if test="enabled[normalize-space(text())='true']">
                <xsl:call-template name="image"/>
                <!-- more header-related elements -->
            </xsl:if>
        </xsl:if>
    </xsl:template>

    <xsl:template name="image" match="*">
        <xsl:if test="img[not(normalize-space(@src)='')]">
            <xsl:copy-of select="img"/>
        </xsl:if>
    </xsl:template>

    <xsl:template name="html" match="*">
        <xsl:param name='lang'/>
        <xsl:if test="current()[@language=$lang]">
            <xsl:value-of select="node()" disable-output-escaping="yes" />
        </xsl:if>
    </xsl:template>

</xsl:stylesheet>

英语

EN EN
法国
fr fr
这就是说,我的解决方案感觉非常冗长,但似乎支持有用的组合和重用属性,这两个属性对我来说非常重要,因为我将需要转换大量结构类似于此示例的XML文档;因此,如果我的大多数XSLT可以重用其他XSLT的一部分,这将非常有用

几点注意事项:

  • 转换速度并不重要,尽管在这方面了解更多可能会很有趣
  • 转换将永远不需要处理编码超过两种示例语言(en和fr)的XML文档

因此,我想了解我的解决方案在您看来是否反惯用,甚至是完全错误的,XSLT争论者。

我会这样写:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="my:my"
exclude-result-prefixes="my">
<xsl:output method="html" indent="yes"/>

<my:language-labels>
    <lang code="en" label="English"/>
    <lang code="fr" label="Francais"/>
</my:language-labels>

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

<xsl:template match="header">
    <xsl:variable name="curLang" select="@language"/>
    <h1>
        <xsl:value-of select="document('')/*/my:language-labels/lang[@code = $curLang]/@label"/>
    </h1>
    <hr/>
    <xsl:copy-of select="img[not(normalize-space(@src) = '')][../enabled[normalize-space() = 'true']]"/>
    <xsl:value-of select="../html[@language = $curLang]" disable-output-escaping="yes"/>
 </xsl:template>

 </xsl:stylesheet>


您的HTML示例看起来已损坏,因此我可能有点错误。我的结果是:

<h1>English</h1>
<hr>
<img src="http://i.stack.imgur.com/xGCNw.gif"> 
<p>En Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
<p>Nunc rutrum, eros sit amet ornare faucibus.</p>
<h1>Francais</h1> 
<hr>
<p>Fr Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
<p>Nunc rutrum, eros sit amet ornare faucibus.</p>
英语

这是一位伟大的精英

努克·鲁特鲁姆,爱神坐在阿梅特·奥纳雷·福西布斯身边

法兰西
神父Lorem ipsum dolor sit amet,献祭精英

努克·鲁特鲁姆,爱神坐在阿梅特·奥纳雷·福西布斯身边

注意事项:

  • 使用谓词。这是一个非常强大的工具
  • 如果可能,将硬编码数据保存在一个位置
  • 应用模板这不是一个神秘的工具,而是一个非常重要的XSLT机制
  • 如果需要的参数是上下文元素,则可以调用normalize space和其他函数,而无需实际传递参数

  • 此转换不包含任何条件XSLT指令或任何命名模板

    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:my="my:my" exclude-result-prefixes="my">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
    
     <my:langs>
      <lang short="en">English</lang>
      <lang short="fr">Français</lang>
     </my:langs>
    
     <xsl:variable name="vLangs" select="document('')/*/my:langs/*"/>
    
     <xsl:template match="header">
      <xsl:apply-templates select="node()|@*"/>
      <hr/>
      <xsl:apply-templates select=
            "../html[@language=current()/@language]/text()"/>
     </xsl:template>
    
     <xsl:template match="header/@language">
      <h1><xsl:value-of select="$vLangs[@short=current()]"/></h1>
     </xsl:template>
    
     <xsl:template match="header[enabled='true']/img[@src and not(@src='')]">
      <xsl:copy-of select="."/>
     </xsl:template>
    
     <xsl:template match="html/text()">
      <xsl:value-of select="." disable-output-escaping="yes"/>
     </xsl:template>
    
     <xsl:template match="html|text()"/>
    </xsl:stylesheet>
    
    <content id="">
        <header language="en">
            <enabled>true</enabled>
            <img src="http://i.stack.imgur.com/xGCNw.gif" />
            <!-- more header-related elements -->
        </header>
        <header language="fr">
            <enabled>false</enabled>
            <img src="" />
            <!-- more header-related elements -->
        </header>
        <html language="en" type="source">
        <![CDATA[
                 <p>En Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
                 <p>Nunc rutrum, eros sit amet ornare faucibus.</p>
                 ]]>
       </html>
        <html language="fr" type="source">
        <![CDATA[
                <p>Fr Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
                <p>Nunc rutrum, eros sit amet ornare faucibus.</p>
                ]]>
     </html>
    </content>
    
    <h1>English</h1>
    <img src="http://i.stack.imgur.com/xGCNw.gif" />
    <hr />
    
                 <p>En Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
                 <p>Nunc rutrum, eros sit amet ornare faucibus.</p>
    
       <h1>Français</h1>
    <hr />
    
                <p>Fr Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
                <p>Nunc rutrum, eros sit amet ornare faucibus.</p>
    
    
    英语
    法国
    
    应用于提供的XML文档时

    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:my="my:my" exclude-result-prefixes="my">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
    
     <my:langs>
      <lang short="en">English</lang>
      <lang short="fr">Français</lang>
     </my:langs>
    
     <xsl:variable name="vLangs" select="document('')/*/my:langs/*"/>
    
     <xsl:template match="header">
      <xsl:apply-templates select="node()|@*"/>
      <hr/>
      <xsl:apply-templates select=
            "../html[@language=current()/@language]/text()"/>
     </xsl:template>
    
     <xsl:template match="header/@language">
      <h1><xsl:value-of select="$vLangs[@short=current()]"/></h1>
     </xsl:template>
    
     <xsl:template match="header[enabled='true']/img[@src and not(@src='')]">
      <xsl:copy-of select="."/>
     </xsl:template>
    
     <xsl:template match="html/text()">
      <xsl:value-of select="." disable-output-escaping="yes"/>
     </xsl:template>
    
     <xsl:template match="html|text()"/>
    </xsl:stylesheet>
    
    <content id="">
        <header language="en">
            <enabled>true</enabled>
            <img src="http://i.stack.imgur.com/xGCNw.gif" />
            <!-- more header-related elements -->
        </header>
        <header language="fr">
            <enabled>false</enabled>
            <img src="" />
            <!-- more header-related elements -->
        </header>
        <html language="en" type="source">
        <![CDATA[
                 <p>En Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
                 <p>Nunc rutrum, eros sit amet ornare faucibus.</p>
                 ]]>
       </html>
        <html language="fr" type="source">
        <![CDATA[
                <p>Fr Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
                <p>Nunc rutrum, eros sit amet ornare faucibus.</p>
                ]]>
     </html>
    </content>
    
    <h1>English</h1>
    <img src="http://i.stack.imgur.com/xGCNw.gif" />
    <hr />
    
                 <p>En Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
                 <p>Nunc rutrum, eros sit amet ornare faucibus.</p>
    
       <h1>Français</h1>
    <hr />
    
                <p>Fr Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
                <p>Nunc rutrum, eros sit amet ornare faucibus.</p>
    
    
    真的
    假的
    这是一位伟大的精英

    努克·鲁特鲁姆,爱神坐在阿梅特·奥纳雷·福西布斯身边

    ]]> 神父Lorem ipsum dolor sit amet,献祭精英

    努克·鲁特鲁姆,爱神坐在阿梅特·奥纳雷·福西布斯身边

    ]]>
    生成所需的正确结果

    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:my="my:my" exclude-result-prefixes="my">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
    
     <my:langs>
      <lang short="en">English</lang>
      <lang short="fr">Français</lang>
     </my:langs>
    
     <xsl:variable name="vLangs" select="document('')/*/my:langs/*"/>
    
     <xsl:template match="header">
      <xsl:apply-templates select="node()|@*"/>
      <hr/>
      <xsl:apply-templates select=
            "../html[@language=current()/@language]/text()"/>
     </xsl:template>
    
     <xsl:template match="header/@language">
      <h1><xsl:value-of select="$vLangs[@short=current()]"/></h1>
     </xsl:template>
    
     <xsl:template match="header[enabled='true']/img[@src and not(@src='')]">
      <xsl:copy-of select="."/>
     </xsl:template>
    
     <xsl:template match="html/text()">
      <xsl:value-of select="." disable-output-escaping="yes"/>
     </xsl:template>
    
     <xsl:template match="html|text()"/>
    </xsl:stylesheet>
    
    <content id="">
        <header language="en">
            <enabled>true</enabled>
            <img src="http://i.stack.imgur.com/xGCNw.gif" />
            <!-- more header-related elements -->
        </header>
        <header language="fr">
            <enabled>false</enabled>
            <img src="" />
            <!-- more header-related elements -->
        </header>
        <html language="en" type="source">
        <![CDATA[
                 <p>En Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
                 <p>Nunc rutrum, eros sit amet ornare faucibus.</p>
                 ]]>
       </html>
        <html language="fr" type="source">
        <![CDATA[
                <p>Fr Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
                <p>Nunc rutrum, eros sit amet ornare faucibus.</p>
                ]]>
     </html>
    </content>
    
    <h1>English</h1>
    <img src="http://i.stack.imgur.com/xGCNw.gif" />
    <hr />
    
                 <p>En Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
                 <p>Nunc rutrum, eros sit amet ornare faucibus.</p>
    
       <h1>Français</h1>
    <hr />
    
                <p>Fr Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
                <p>Nunc rutrum, eros sit amet ornare faucibus.</p>
    
    英语
    
    这是一位伟大的精英

    努克·鲁特鲁姆,爱神坐在阿梅特·奥纳雷·福西布斯身边

    法国
    神父Lorem ipsum dolor sit amet,献祭精英

    努克·鲁特鲁姆,爱神坐在阿梅特·奥纳雷·福西布斯身边

    注意事项

    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:my="my:my" exclude-result-prefixes="my">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
    
     <my:langs>
      <lang short="en">English</lang>
      <lang short="fr">Français</lang>
     </my:langs>
    
     <xsl:variable name="vLangs" select="document('')/*/my:langs/*"/>
    
     <xsl:template match="header">
      <xsl:apply-templates select="node()|@*"/>
      <hr/>
      <xsl:apply-templates select=
            "../html[@language=current()/@language]/text()"/>
     </xsl:template>
    
     <xsl:template match="header/@language">
      <h1><xsl:value-of select="$vLangs[@short=current()]"/></h1>
     </xsl:template>
    
     <xsl:template match="header[enabled='true']/img[@src and not(@src='')]">
      <xsl:copy-of select="."/>
     </xsl:template>
    
     <xsl:template match="html/text()">
      <xsl:value-of select="." disable-output-escaping="yes"/>
     </xsl:template>
    
     <xsl:template match="html|text()"/>
    </xsl:stylesheet>
    
    <content id="">
        <header language="en">
            <enabled>true</enabled>
            <img src="http://i.stack.imgur.com/xGCNw.gif" />
            <!-- more header-related elements -->
        </header>
        <header language="fr">
            <enabled>false</enabled>
            <img src="" />
            <!-- more header-related elements -->
        </header>
        <html language="en" type="source">
        <![CDATA[
                 <p>En Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
                 <p>Nunc rutrum, eros sit amet ornare faucibus.</p>
                 ]]>
       </html>
        <html language="fr" type="source">
        <![CDATA[
                <p>Fr Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
                <p>Nunc rutrum, eros sit amet ornare faucibus.</p>
                ]]>
     </html>
    </content>
    
    <h1>English</h1>
    <img src="http://i.stack.imgur.com/xGCNw.gif" />
    <hr />
    
                 <p>En Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
                 <p>Nunc rutrum, eros sit amet ornare faucibus.</p>
    
       <h1>Français</h1>
    <hr />
    
                <p>Fr Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
                <p>Nunc rutrum, eros sit amet ornare faucibus.</p>
    
  • 模板和模式匹配的使用

  • 使用

  • 在模板的匹配模式中以及在


  • 您编写的[它]似乎支持有用的合成和重用属性。对于那些CDATA部分,我不这么认为……是的,但我无法控制XML源:\好问题,+1。请参阅我的答案,了解不使用任何xslt条件指令和任何命名模板的解决方案。看看这是否有助于您非常简洁!!!非常感谢您的回答和注释。虽然我接受了@Dimitre Novatchev的回答,但我仍然使用了您的一些见解和技巧。我非常喜欢您所提供的模式匹配。这使得模板非常模块化。非常感谢您的回答。奇怪的是,这段代码
    使我以前基于xalan的实现失败,出现了
    NullPointerException
    。(还有@Flack的等效代码。)因此,在升级XSLT处理器之前,我跳过了sweet变量的用法,只输出语言的短名称。@Daniel Jomphe:解决方法是:
    @Dimitre Novatchev:我尝试了,但没有成功。谢谢你的努力。