从SQL到XML的XSLT转换

时间:2014-07-10 11:41:04

标签: xml xslt

我有以下问题:

我正在使用带有

的SQL语句
<table name="VDR_10" namecase="lower">
        <sql><![CDATA[" SQL-Select "]]></sql>
</table>

获取下表

    P1  P2  ident
    3   702 XS0419605406
    3   702 XS0188568751
    4   702 XXXXXXXXXXXX
    4   702 XS1048428012
    3   701 AT0000A0N9A0
    3   701 XS0418690201
    3   701 XS0417728325
    3   701 BE0000314238
    3   701 ES0000101339

我的xslt看起来像这样:

    <xsl:key name="vdr10_kennzahl" match="VDR_10" use="p2"/>

    <xsl:template match="VDR_10">
        <xsl:variable name="this" select="."/>
        <xsl:for-each select="$this[generate-id(.)=generate-id(key('vdr10_kennzahl', p2))]">
            <xsl:sort select="p2" order="ascending"/>
            <POSTEN>
                <xsl:attribute name="p1-id"><xsl:value-of select="p1"/></xsl:attribute>
                <xsl:attribute name="p2-id"><xsl:value-of select="p2"/></xsl:attribute>
                <xsl:for-each select="key('vdr10_kennzahl',p2)">
                    <IDENT-Zeile>
                        <BETRAG>
                            <xsl:value-of select="ident"/>
                        </BETRAG>
                    </IDENT-ZEILE>
                </xsl:for-each>
            </POSTEN>
        </xsl:for-each>
    </xsl:template>

输出看起来像这样:

    <POSTEN p1-id="3" p2-id ="702"> 
        <IDENT-zeile>XS0419605406</IDENT-zeile>
        <IDENT-zeile>XS0188568751</IDENT-zeile>
        <IDENT-zeile>XXXXXXXXXXXX</IDENT-zeile>
        <IDENT-zeile>XS1048428012</IDENT-zeile>
    </POSTEN>   


    <POSTEN p1-id="3" p2-id ="701"> 
        <IDENT-zeile>AT0000A0N9A0</IDENT-zeile>
        <IDENT-zeile>XS0418690201</IDENT-zeile>
        <IDENT-zeile>XS0417728325</IDENT-zeile>
        <IDENT-zeile>BE0000314238</IDENT-zeile>
        <IDENT-zeile>ES0000101339</IDENT-zeile>
    </POSTEN>

这不是我想要的。我需要'像这样的输出

    <POSTEN p1-id="3" p2-id ="702"> 
        <IDENT-zeile>XS0419605406</IDENT-zeile> 
        <IDENT-zeile>XS0188568751</IDENT-zeile>
    </POSTEN>   

    <POSTEN p1-id="4" p2-id ="702"> 
        <IDENT-zeile>XXXXXXXXXXXX</IDENT-zeile>
        <IDENT-zeile>XS1048428012</IDENT-zeile>
    </POSTEN>

    <POSTEN p1-id="3" p2-id ="701">     
        <IDENT-zeile>AT0000A0N9A0</IDENT-zeile>
        <IDENT-zeile>XS0418690201</IDENT-zeile>
        <IDENT-zeile>XS0417728325</IDENT-zeile>
        <IDENT-zeile>BE0000314238</IDENT-zeile>
        <IDENT-zeile>ES0000101339</IDENT-zeile>
    </POSTEN>

我想我需要另外一个。但我不知道如何使用它。有人可以帮帮我吗?

1 个答案:

答案 0 :(得分:0)

问题是,当您需要对“p1”和“p2”进行分组时,您当前只对“p2”值进行分组。因此,您的密钥需要看起来像这样

<xsl:key name="vdr10_kennzahl" match="VDR_10" use="concat(p1, '|', p2)"/>

无论您何时访问密钥

,都可以使用“concat”
 <xsl:for-each 
     select="$this[generate-id(.)=generate-id(key('vdr10_kennzahl', concat(p1, '|', p2)))]">

话虽如此, xsl:for-each 有点不必要,因为它只会为匹配的当前 VDR_10 返回一个值。最好让模板上的条件匹配,如下所示:

<xsl:template match="VDR_10[generate-id(.)=generate-id(key('vdr10_kennzahl', concat(p1, '|', p2)))]">

您还需要另一个模板来匹配所有其他 VDR_10 元素,以忽略它们

<xsl:template match="VDR_10" />

(更具体的模板总是在这里获得优先权。)

最后,如果您希望对结果进行排序,您可以将逻辑添加到父元素,并按排序顺序选择子节点

<xsl:template match="table">
  <xsl:apply-templates select="VDR_10">
      <xsl:sort select="p1" />
      <xsl:sort select="p2" />
  </xsl:apply-templates>
</xsl:template>

例如,试试这个XSLT(注意使用属性值模板创建“p1-id”和“p2-id”属性,以减小XSLT的大小)

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output omit-xml-declaration="yes" indent="yes" />
   <xsl:key name="vdr10_kennzahl" match="VDR_10" use="concat(p1, '|', p2)"/>


    <xsl:template match="table">
      <xsl:apply-templates select="VDR_10">
          <xsl:sort select="p1" />
          <xsl:sort select="p2" />
      </xsl:apply-templates>
    </xsl:template>

    <xsl:template match="VDR_10[generate-id(.)=generate-id(key('vdr10_kennzahl', concat(p1, '|', p2)))]">
       <POSTEN p1-id="{p1}" p2-id="{p2}">
            <xsl:for-each select="key('vdr10_kennzahl',concat(p1, '|', p2))">
                <IDENT-zeile>
                      <xsl:value-of select="ident"/>
                 </IDENT-zeile>
            </xsl:for-each>
        </POSTEN>
    </xsl:template>

    <xsl:template match="VDR_10" />
</xsl:stylesheet> 

应用于此XML

<table>
    <VDR_10><p1>3</p1><p2>702</p2><ident>XS0419605406</ident></VDR_10>
    <VDR_10><p1>3</p1><p2>702</p2><ident>XS0188568751</ident></VDR_10>
    <VDR_10><p1>4</p1><p2>702</p2><ident>XXXXXXXXXXXX</ident></VDR_10>
    <VDR_10><p1>4</p1><p2>702</p2><ident>XS1048428012</ident></VDR_10>
    <VDR_10><p1>3</p1><p2>701</p2><ident>AT0000A0N9A0</ident></VDR_10>
    <VDR_10><p1>3</p1><p2>701</p2><ident>XS0418690201</ident></VDR_10>
    <VDR_10><p1>3</p1><p2>701</p2><ident>XS0417728325</ident></VDR_10>
    <VDR_10><p1>3</p1><p2>701</p2><ident>BE0000314238</ident></VDR_10>
    <VDR_10><p1>3</p1><p2>701</p2><ident>ES0000101339</ident></VDR_10>
</table>

以下是输出

<POSTEN p1-id="3" p2-id="701">
  <IDENT-zeile>AT0000A0N9A0</IDENT-zeile>
  <IDENT-zeile>XS0418690201</IDENT-zeile>
  <IDENT-zeile>XS0417728325</IDENT-zeile>
  <IDENT-zeile>BE0000314238</IDENT-zeile>
  <IDENT-zeile>ES0000101339</IDENT-zeile>
</POSTEN>
<POSTEN p1-id="3" p2-id="702">
  <IDENT-zeile>XS0419605406</IDENT-zeile>
  <IDENT-zeile>XS0188568751</IDENT-zeile>
</POSTEN>
<POSTEN p1-id="4" p2-id="702">
  <IDENT-zeile>XXXXXXXXXXXX</IDENT-zeile>
  <IDENT-zeile>XS1048428012</IDENT-zeile>
</POSTEN>