xslt多次重用密钥

时间:2015-02-18 10:33:42

标签: xml xslt

上下文:开始学习xslt,并在分组/键上遇到问题

所以,我有这个输入XML:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="getInfoMinimal.xml" type="text/xsl" ?>
<domaines>
    <domaine Name="someDomain">
        <application name="someApplication1">
            <module id="0001">
                <env-entry>ejb/test</env-entry>
                <requirement>Queue1</requirement>
            </module>
            <module id="0002">
                <env-entry>ejb/notherTest</env-entry>
                <requirement>Queue1</requirement>
            </module>
            <module id="0003">
                <env-entry>ejb/notherTest2</env-entry>
                <requirement>Datasource1</requirement>
            </module>
            <module id="0004">
                <env-entry>ejb/notherTest3</env-entry>
                <requirement>Datasource1</requirement>
            </module>
        </application>
        <application name="someApplication2">
            <module id="0001">
                <env-entry>ejb/test</env-entry>
                <requirement>Queue1</requirement>
            </module>
            <module id="0002">
                <env-entry>ejb/notherTest</env-entry>
                <requirement>Queue1</requirement>
            </module>
            <module id="0003">
                <env-entry>ejb/notherTest2</env-entry>
                <requirement>Datasource1</requirement>
            </module>
            <module id="0004">
                <env-entry>ejb/notherTest3</env-entry>
                <requirement>Datasource1</requirement>
            </module>
            <module id="0001">
                <env-entry>ejb/test</env-entry>
                <requirement>Queue1</requirement>
            </module>
            <module id="0002">
                <env-entry>ejb/notherTest</env-entry>
                <requirement>Queue1</requirement>
            </module>
            <module id="0003">
                <env-entry>ejb/notherTest2</env-entry>
                <requirement>Datasource1</requirement>
            </module>
            <module id="0004">
                <env-entry>ejb/notherTest3</env-entry>
                <requirement>Datasource3</requirement>
            </module>
        </application>
    </domaine>
</domaines>

和这个xlst文件(getInfoMinimal.xml):

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">

    <xsl:output method="xml" indent="yes" encoding="UTF-8"/>

    <xsl:key name="modules-by-requirement" match="module" use="requirement" />

    <xsl:template match="/">
        <html>
            <head>
                <title><xsl:value-of select="/domaines/domaine/@Name"/></title>
            </head>
            <body>
                <xsl:for-each select="/domaines/domaine/application">
                    <h1><xsl:value-of select="./@name"/></h1>
                    <xsl:for-each select="module[count(. | key('modules-by-requirement', requirement)[1]) = 1]">
                        <!--<xsl:sort select="requirement" />-->
                        <xsl:value-of select="requirement" /><br />
                        <xsl:for-each select="key('modules-by-requirement', requirement)">
                        <!--<xsl:sort select="env-entry" />
                        <xsl:value-of select="env-entry" /> (<xsl:value-of select="blabla" />)<br />-->
                        </xsl:for-each>
                    </xsl:for-each>
                </xsl:for-each>
            </body>
        </html>
    </xsl:template>

</xsl:stylesheet>

我试图将其呈现到一个html页面,该页面列出了每个应用程序模块所具有的所有要求。

输入XML隐含的规则:

  • 1个应用程序可以有1个或更多模块

  • 1个模块可以有1个或多个独特要求

  • 多个模块可以具有相同的要求

  • 多个应用程序不能具有相同的模块

  • 多个应用程序可以具有相同的要求。

当前结果:

someApplication1

  • 队列1

  • Datasource1

someApplication2

  • Datasource3

想要的结果:

someApplication1

  • 队列1

  • Datasource1

someApplication2

  • 队列1

  • Datasource1

  • Datasource3

如您所见,Queue1和Datasource1不在&#39; someApplication2&#39;结果,即使我想要它们。

任何和所有帮助将不胜感激

1 个答案:

答案 0 :(得分:1)

由于您需要为每个应用程序/需求组合使用不同的密钥,因此可以使用应用程序名称和需求名称的串联作为键值:

<xsl:key name="modules-by-requirement" match="module" 
         use="concat(../@name, '+', requirement)" />

然后完整的解决方案看起来像这样(清理了一下使用模板和更有效的Muenchian分组样式):

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

  <xsl:output method="xml" indent="yes" encoding="UTF-8" omit-xml-declaration="yes"/>

  <xsl:key name="modules-by-requirement" match="module" 
           use="concat(../@name, '+', requirement)" />

  <xsl:template match="/">
    <html>
      <head>
        <title>
          <xsl:value-of select="/domaines/domaine/@Name"/>
        </title>
      </head>
      <body>
        <xsl:apply-templates select="/domaines/domaine/application" />
      </body>
    </html>
  </xsl:template>

  <xsl:template match="application">
    <xsl:variable name="appName" select="@name"/>
    <h1>
      <xsl:value-of select="$appName"/>
    </h1>
    <xsl:variable name="distinctModules"
                  select="module[generate-id() = 
                                 generate-id(key('modules-by-requirement', 
                                                 concat($appName, '+', requirement))[1])
                                ]" />
    <xsl:if test="$distinctModules">
    <ul>
      <xsl:apply-templates select="$distinctModules" />
    </ul>
    </xsl:if>
  </xsl:template>

  <xsl:template match="module">
    <li>
      <xsl:value-of select="requirement" />
    </li>
  </xsl:template>

</xsl:stylesheet>

在样本输入上运行时,结果为:

<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>someDomain</title>
  </head>
  <body>
    <h1>someApplication1</h1>
    <ul>
      <li>Queue1</li>
      <li>Datasource1</li>
    </ul>
    <h1>someApplication2</h1>
    <ul>
      <li>Queue1</li>
      <li>Datasource1</li>
      <li>Datasource3</li>
    </ul>
  </body>
</html>