XSLT按元素名称分组

时间:2015-07-19 23:53:15

标签: xml xslt parent-child grouping

我是XSLt的新手。我需要在配置文件中查找输入XML中的元素,并根据它生成输出。查找值可以在任何名为“Exception”的子elemnet中。以下是输入示例 输入XML

 <output>
    <groups>
    <Exception_laptop>
            <Exception_laptop_code>100</Exception_laptop_code>
            <Exception_laptop_string>1414</Exception_laptop_string>
</Exception_laptop>
    <Exception_laptop>
            <Exception_laptop_code>-1210</Exception_laptop_code>
            <Exception_laptop_string>126</Exception_laptop_string>
    </Exception_laptop>
    <Exception_computer>
            <Exception_computer_code>111</Exception_computer_code>
            <Exception_computer_string>163</Exception_computer_string>
        </Exception_computer>
        <Exception_computer>
            <Exception_computer_code>100</Exception_computer_code>
            <Exception_computer_string>1414</Exception_computer_string>
        </Exception_computer>
        <UnitId>134</UnitId>
        <origin>1.0</origin>
    </groups>
</output>

输出应该如下所示

预期输出

<ResponseMessages>
<OutGroupMessages>
    <ExceptionGroup>Exception_laptop</ExceptionGroup>
    <ExceptionMessages>
        <Message>
            <Identifier>11</Identifier>
            <Message>message1</Message>
        </Message>
        <Message>
            <Identifier>12</Identifier>
            <Message>message2</Message>
        </Message>
    </ExceptionMessages>
</OutGroupMessages>
<OutGroupMessages>
<ExceptionGroup>Exception_computer</ExceptionGroup>
    <ExceptionMessages>
        <Message>
            <Identifier>15</Identifier>
            <Message>message4</Message>
        </Message>
        <Message>
            <Identifier>11</Identifier>
            <Message>message1</Message>
        </Message>
    </ExceptionMessages>
</OutGroupMessages>

我正在使用下面的xslt,但我对如何将'OutGroupMessages'父级添加到每个异常组有点遗失。

XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xalan="http://xml.apache.org/xslt" xmlns:str="http://exslt.org/strings"
    xmlns:set="http://exslt.org/sets" xmlns:math="http://exslt.org/math"
    xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:regexp="http://exslt.org/regular-expressions"
    xmlns:dyn="http://exslt.org/dynamic" xmlns:dp="http://www.datapower.com/extensions"
    xmlns:exsl="http://exslt.org/common" xmlns:date="http://exslt.org/dates-and-times"
    xmlns:io="http://www.w3.org/2003/05/soap-envelope" xmlns:io3="http://www.ibm.com/xmlns/prod/websphere/mq/sca/6.0.0"
    xmlns:io2="http://www.ibm.com/websphere/sibx/smo/v6.0.1" xmlns:io4="http://schemas.xmlsoap.org/ws/2004/08/addressing"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:io5="http://www.ibm.com/xmlns/prod/websphere/http/sca/6.1.0"
    xmlns:xs4xs="http://www.w3.org/2001/XMLSchema" xmlns:io6="http://www.w3.org/2005/08/addressing"
    version="1.0">

        <xsl:template name="mapExceptions">
            <xsl:param name="exceptions"/>
            <ResponseMessages>
                <xsl:if test="boolean(//*[contains(local-name(.),'Exception')])">
                <OutGroupMessages>
                    <xsl:apply-templates mode="Exception" select="$exceptions/output/groups/*"/>
                    </OutGroupMessages>
                </xsl:if>
            </ResponseMessages>
        </xsl:template>


        <xsl:template match="//*[contains(local-name(),'Exception')]" mode="Exception">

                <xsl:if test="local-name(preceding-sibling::*[1]) != local-name(.)">
                    <xsl:element name="ExceptionGroup">
                        <xsl:value-of select="local-name(.)"/>
                    </xsl:element>
                </xsl:if>
                <ExceptionMessages>
                    <xsl:call-template name="mapError">
                        <xsl:with-param name="errorcode">
                            <xsl:value-of select="./*[contains(local-name(.),'_code')]"/>
                        </xsl:with-param>
                        <xsl:with-param name="errorString">
                            <xsl:value-of select="./*[contains(local-name(.),'_string')]"/>
                        </xsl:with-param>
                    </xsl:call-template>
                </ExceptionMessages>

        </xsl:template>

        <xsl:template name="mapError">
            <xsl:param name="errorcode"/>
            <xsl:param name="errorstring"/>
            <xsl:variable name="config" select="'ErrorMapperConfig.xml'"/>
            <xsl:variable name="errorconfig" select="document($config)"/>
            <xsl:for-each select="$errorconfig/ErrorConfig/Error">
                <xsl:if test="ErrorCode = $errorcode and ErrorString= $errorstring">
                    <Message>
                        <xsl:element name="Identifier">
                            <xsl:value-of select="Identifier"/>
                        </xsl:element>
                        <xsl:element name="Message">
                            <xsl:value-of select="/Message"/>
                        </xsl:element>
                    </Message>
                </xsl:if>
            </xsl:for-each>
        </xsl:template>

    </xsl:stylesheet>

输出我

   <ResponseMessages>
    <OutGroupMessages>
        <ExceptionGroup>Exception_laptop</ExceptionGroup>
        <ExceptionMessages>
            <Message>
                <Identifier>11</Identifier>
                <Message>message1</Message>
            </Message>
        </ExceptionMessages>
        <ExceptionMessages>
            <Message>
                <Identifier>12</Identifier>
                <Message>message2</Message>
            </Message>
        </ExceptionMessages>
        <ExceptionGroup>Exception_computer</ExceptionGroup>
        <ExceptionMessages>
            <Message>
                <Identifier>15</Identifier>
                <Message>message4</Message>
            </Message>
        </ExceptionMessages>
        <ExceptionMessages>
            <Message>
                <Identifier>11</Identifier>
                <Message>message1</Message>
            </Message>
        </ExceptionMessages>
    </OutGroupMessages>
</ResponseMessages>

提前致谢

1 个答案:

答案 0 :(得分:1)

如果您使用的是XSLT 1.0,则应学习如何使用Muenchian grouping。在您的情况下,这看起来像:

XSLT 1。

<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:key name="elem-by-name" match="groups/*" use="name()" />

<xsl:template match="/output">
    <ResponseMessages>
        <!-- for each distinct exception group -->
        <xsl:for-each select="groups/*[starts-with(name(), 'Exception_')][count(. | key('elem-by-name', name())[1]) = 1]">
            <OutGroupMessages>
                <ExceptionGroup>
                    <xsl:value-of select="name()"/>
                </ExceptionGroup>
                <!-- for each member of current group -->
                <xsl:for-each select="key('elem-by-name', name())">
                    <Message>
                        <Identifier>
                            <xsl:value-of select="*[contains(name(), '_code')]"/>
                        </Identifier>
                        <Message>
                            <xsl:value-of select="*[contains(name(), '_string')]"/>
                        </Message>
                    </Message>
                </xsl:for-each>
            </OutGroupMessages>
        </xsl:for-each>
    </ResponseMessages>
</xsl:template>

</xsl:stylesheet>

应用于您的输入示例,结果将是:

<?xml version="1.0" encoding="UTF-8"?>
<ResponseMessages>
   <OutGroupMessages>
      <ExceptionGroup>Exception_laptop</ExceptionGroup>
      <Message>
         <Identifier>100</Identifier>
         <Message>1414</Message>
      </Message>
      <Message>
         <Identifier>-1210</Identifier>
         <Message>126</Message>
      </Message>
   </OutGroupMessages>
   <OutGroupMessages>
      <ExceptionGroup>Exception_computer</ExceptionGroup>
      <Message>
         <Identifier>111</Identifier>
         <Message>163</Message>
      </Message>
      <Message>
         <Identifier>100</Identifier>
         <Message>1414</Message>
      </Message>
   </OutGroupMessages>
</ResponseMessages>

我不确定 预期输出中的值来自何处:在输入中找不到它们,而不是在样式表中。