-2

我有一个 xml 文件:

<PRODUCTS>
  <PRODUCT>
    <NAME_EN>jacket</NAME_EN>
    <SKU>1</SKU>
    <SIZE>
      <CODE>01 </CODE>
      <DESCRIPTION>34</DESCRIPTION>
    </SIZE>
    <COLOR>
      <DESCRIPTION_EN>black</DESCRIPTION_EN>
    </COLOR>
  </PRODUCT>
  <PRODUCT>
    <NAME_EN>jacket</NAME_EN>
    <SKU>2</SKU>
    <SIZE>
      <CODE>02</CODE>
      <DESCRIPTION>35</DESCRIPTION>
    </SIZE>
    <COLOR>
      <DESCRIPTION_EN>black</DESCRIPTION_EN>
    </COLOR>
  </PRODUCT>
  <PRODUCT>
    <NAME_EN>shoes</NAME_EN>
    <SKU>3</SKU>
    <SIZE>
      <CODE>01</CODE>
      <DESCRIPTION>34</DESCRIPTION>
    </SIZE>
    <COLOR>
      <DESCRIPTION_EN>black</DESCRIPTION_EN>
    </COLOR>
  </PRODUCT>
</PRODUCTS>

我想使用 xsl 转换来实现这样的结果:

<catalog>
  <product>
    <variants>
      <variant>
        <sku>1</sku>        
        <options>
          <option>
            <code>size</code>
            <value>34</value>
          </option>
        </options>
      </variant>
      <variant>
        <sku>2</sku>        
        <options>
          <option>
            <code>size</code>
            <value>35</value>
          </option>
        </options>
      </variant>
    </variants>
  </product>
  <product>
    <variants>
      <variant>
        <sku>3</sku>        
        <options>
          <option>
            <code>size</code>
            <value>34</value>
          </option>
        </options>
      </variant>
    </variants>
  </product>
</catalog>

我需要的是在所有节点上 for-each名称相同的位置NAME_EN和位置。COLOR/DESCRIPTION_EN

我知道这样的for-each:

<xsl:for-each select="PRODUCTS/PRODUCT[NAME_EN='jacket']">

但它不会为我分叉。有什么办法可以做到这一点?

4

3 回答 3

1

这是使用 XSLT 1.0 和 Muenchian 方法按NAME_EN字段值对产品进行分组的解决方案。

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

    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:key name="product-by-name" match="PRODUCT" use="NAME_EN"/>

    <xsl:template match="/PRODUCTS">
        <products>
            <xsl:apply-templates select="PRODUCT"/>
        </products>
    </xsl:template>

    <xsl:template match="PRODUCT">
        <xsl:variable name="name-group" select="key('product-by-name', NAME_EN)"/>
        <xsl:if test="generate-id() = generate-id($name-group[1])">
            <product>
                <variants>
                    <xsl:for-each select="$name-group">
                        <variant>
                            <xsl:apply-templates select="SKU"/>
                            <options>
                                <xsl:apply-templates select="SIZE"/>
                            </options>
                        </variant>
                    </xsl:for-each>
                </variants>
            </product>
        </xsl:if>
    </xsl:template>

    <xsl:template match="SKU">
        <sku><xsl:value-of select="."/></sku>
    </xsl:template>

    <xsl:template match="SIZE">
        <option>
            <code>size</code>
            <value><xsl:value-of select="DESCRIPTION"/></value>
        </option>
    </xsl:template>

</xsl:stylesheet>

输出

<products>
   <product>
      <variants>
         <variant>
            <sku>1</sku>
            <options>
               <option>
                  <code>size</code>
                  <value>34</value>
               </option>
            </options>
         </variant>
         <variant>
            <sku>2</sku>
            <options>
               <option>
                  <code>size</code>
                  <value>35</value>
               </option>
            </options>
         </variant>
      </variants>
   </product>
   <product>
      <variants>
         <variant>
            <sku>3</sku>
            <options>
               <option>
                  <code>size</code>
                  <value>34</value>
               </option>
            </options>
         </variant>
      </variants>
   </product>
</products>
于 2013-04-11T12:57:06.300 回答
0

这是完整的解决方案:

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

  <xsl:template match="NAME_EN | DESCRIPTION_EN"/>

  <xsl:template match="/">
    <catalog>
      <xsl:call-template name="product"/>
    </catalog>
  </xsl:template>


  <xsl:template name="product">
    <xsl:for-each-group select="//NAME_EN" group-by="text()">
      <xsl:for-each select="current-grouping-key()">
        <product>
          <variants>
            <xsl:for-each select="current-group()/parent::PRODUCT">
              <variant>
                <xsl:apply-templates/>
              </variant>
            </xsl:for-each>
          </variants>
        </product>
      </xsl:for-each>
    </xsl:for-each-group>
  </xsl:template>

  <xsl:template match="SKU">
    <sku>
      <xsl:apply-templates/>
    </sku>
  </xsl:template>

  <xsl:template match="SIZE">
    <options>
      <option>
        <xsl:apply-templates/>
      </option>
    </options>
  </xsl:template>

  <xsl:template match="CODE">
    <code>
      <xsl:apply-templates/>
    </code>
  </xsl:template>

  <xsl:template match="DESCRIPTION">
    <value>
      <xsl:apply-templates/>
    </value>
  </xsl:template>
</xsl:stylesheet>
于 2013-04-11T13:49:13.313 回答
0

我认为@Efrain 是对的,你锁定的是分组。<xsl:for-each-group> 仅适用于 xslt 2.0。有关更多信息,请查看例如:how to apply group by on xslt elements

于 2013-04-11T10:44:59.810 回答