0

我在 XSLT 转换方面遇到了一点问题,我需要你的帮助。我从数据库过程中收到如下数据,我需要将其转换为较少冗余的结构。

输入数据的结构是:一级订单&产品&产品属性。这是一个例子:

<root>
    <Order>
        <order_id>1</order_id>
        <order_category>Internet Services</order_category>
        <product_id>14</product_id>
        <product_name>Mobile Internet - standard</product_name>
        <product_amount>1</product_amount>
        <product_price>9.99</product_price>
        <attribute_id>1</attribute_id>
        <attribute_name>Discount</attribute_name>
        <attribute_value>20%</attribute_value>
    </Order>
    <Order>
        <order_id>1</order_id>
        <order_category>Internet Services</order_category>
        <product_id>14</product_id>
        <product_name>Mobile Internet - standard</product_name>
        <product_amount>1</product_amount>
        <product_price>9.99</product_price>
        <attribute_id>4</attribute_id>
        <attribute_name>Additional service</attribute_name>
        <attribute_value>Night free</attribute_value>
    </Order>
    <Order>
        <order_id>1</order_id>
        <order_category>Internet Services</order_category>
        <product_id>17</product_id>
        <product_name>Activation</product_name>
        <product_amount>100</product_amount>
        <product_price>0</product_price>
        <attribute_id>1</attribute_id>
        <attribute_name>Volume</attribute_name>
        <attribute_value>GB</attribute_value>
    </Order>
    <Order>
        <order_id>2</order_id>
        <order_category>Device Services</order_category>
        <product_id>421</product_id>
        <product_name>Modem TS2.3</product_name>
        <product_amount>1</product_amount>
        <product_price>14.99</product_price>
        <attribute_id>4</attribute_id>
        <attribute_name>Model</attribute_name>
        <attribute_value>TS2.3</attribute_value>
    </Order>
    <Order>
        <order_id>2</order_id>
        <order_category>Device Services</order_category>
        <product_id>421</product_id>
        <product_name>Modem TS2.3</product_name>
        <product_amount>1</product_amount>
        <product_price>14.99</product_price>
        <attribute_id>17</attribute_id>
        <attribute_name>SATA</attribute_name>
        <attribute_value>4</attribute_value>
    </Order>
    <Order>
        <order_id>2</order_id>
        <order_category>Device Services</order_category>
        <product_id>16743</product_id>
        <product_name>Printer XLV 14</product_name>
        <product_amount>1</product_amount>
        <product_price>30.99</product_price>
        <attribute_id>4</attribute_id>
        <attribute_name>Duplex</attribute_name>
        <attribute_value>Y</attribute_value>
    </Order>
</root>

上面的数据是多余的,因为只有两个订单(order_id=1 和 order_id=2),这些订单出现了 6 次。同样的问题也发生在产品上。输出的结构应该减少冗余:订单可能有多个产品之一,每个产品可能包含零个或多个属性。下面列出了示例输出:

<root>
    <Order>
        <order_id>1</order_id>
        <order_category>Internet Services</order_category>
        <products>
            <product>
                <id>14</id>
                <name>Mobile Internet - standard</name>
                <amount>1</amount>
                <price>9.99</price>
                <attributes>
                    <attribute>
                        <id>1</id>
                        <name>Discount</name>
                        <value>20%</value>
                    </attribute>
                    <attribute>
                        <id>4</id>
                        <name>Additional service</name>
                        <value>Night free</value>
                    </attribute>
                </attributes>
            </product>
            <product>
                <id>17</id>
                <name>Activation</name>
                <amount>100</amount>
                <price>0</price>
                <attributes>
                    <attribute>
                        <id>1</id>
                        <name>Volume</name>
                        <value>GB</value>
                    </attribute>
                </attributes>
            </product>
        </products>
    </Order>
    <Order>
        <order_id>2</order_id>
        <order_category>Device Services</order_category>
        <products>
            <product>
                <id>421</id>
                <name>Modem TS2.3</name>
                <amount>1</amount>
                <price>14.99</price>
                <attributes>
                    <attribute>
                        <id>4</id>
                        <name>Model</name>
                        <value>TS2.3</value>
                    </attribute>
                    <attribute>
                        <id>17</id>
                        <name>SATA</name>
                        <value>4</value>
                    </attribute>
                </attributes>
            </product>
            <product>
                <id>16743</id>
                <name>Printer XLV 14</name>
                <amount>1</amount>
                <price>30.99</price>
                <attributes>
                    <attribute>
                        <id>4</id>
                        <name>Duplex</name>
                        <value>Y</value>
                    </attribute>
                </attributes>
            </product>
        </products>
    </Order>
</root>

问题是正确嵌套数据并删除冗余部分。我可以请你帮忙解决这个相当困难的问题吗?:)

4

1 回答 1

0

您可以通过使用分组来完成此操作:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
  <xsl:key name="kOrder" match="Order" use="order_id" />
  <xsl:key name="kOrderProd" match="Order" 
           use="concat(order_id, '+', product_id)"/>

  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="/*">
    <xsl:copy>
      <xsl:apply-templates 
         select="Order[generate-id() = 
                       generate-id(key('kOrder', order_id)[1])]"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="Order">
    <xsl:copy>
      <xsl:apply-templates select="order_id | order_category" />
      <products>
        <xsl:apply-templates
          select="key('kOrder', order_id)
                     [generate-id() =
                      generate-id(key('kOrderProd', 
                                      concat(order_id, '+', product_id))[1])]" 
          mode="product" />
      </products>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="Order" mode="product">
    <product>
      <xsl:apply-templates select="*[starts-with(local-name(), 'product_')]" 
                           mode="stripPrefix" />
      <attributes>
        <xsl:apply-templates select="key('kOrderProd', 
                                         concat(order_id, '+', product_id))"
                             mode="attribute"/>
      </attributes>
    </product>
  </xsl:template>

  <xsl:template match="*" mode="stripPrefix">
    <xsl:element name="{substring-after(local-name(), '_')}">
      <xsl:apply-templates select="@* | node()" />
    </xsl:element>
  </xsl:template>

  <xsl:template match="Order" mode="attribute">
    <attribute>
      <xsl:apply-templates select="*[starts-with(local-name(), 'attribute_')]" 
                           mode="stripPrefix" />
    </attribute>
  </xsl:template>
</xsl:stylesheet>

在您的示例输入上运行时,结果是:

<root>
  <Order>
    <order_id>1</order_id>
    <order_category>Internet Services</order_category>
    <products>
      <product>
        <id>14</id>
        <name>Mobile Internet - standard</name>
        <amount>1</amount>
        <price>9.99</price>
        <attributes>
          <attribute>
            <id>1</id>
            <name>Discount</name>
            <value>20%</value>
          </attribute>
          <attribute>
            <id>4</id>
            <name>Additional service</name>
            <value>Night free</value>
          </attribute>
        </attributes>
      </product>
      <product>
        <id>17</id>
        <name>Activation</name>
        <amount>100</amount>
        <price>0</price>
        <attributes>
          <attribute>
            <id>1</id>
            <name>Volume</name>
            <value>GB</value>
          </attribute>
        </attributes>
      </product>
    </products>
  </Order>
  <Order>
    <order_id>2</order_id>
    <order_category>Device Services</order_category>
    <products>
      <product>
        <id>421</id>
        <name>Modem TS2.3</name>
        <amount>1</amount>
        <price>14.99</price>
        <attributes>
          <attribute>
            <id>4</id>
            <name>Model</name>
            <value>TS2.3</value>
          </attribute>
          <attribute>
            <id>17</id>
            <name>SATA</name>
            <value>4</value>
          </attribute>
        </attributes>
      </product>
      <product>
        <id>16743</id>
        <name>Printer XLV 14</name>
        <amount>1</amount>
        <price>30.99</price>
        <attributes>
          <attribute>
            <id>4</id>
            <name>Duplex</name>
            <value>Y</value>
          </attribute>
        </attributes>
      </product>
    </products>
  </Order>
</root>
于 2013-04-16T21:41:05.723 回答