0

我想通过 xslt 使用 php 将 xml 文件转换为另一个文件。在输出上我需要一些调整,但我不知道如何调整我的 xsl 样式表。

谢谢你的帮助

需要对输出进行调整:

  • 向类别元素添加动态计数,例如<category1> <category2>...
  • 将 PRODUCT/COLORS/COLOR/AVAILABLE_SIZE 的元素 SIZE 的所有内容添加到<$color>类似元素<green>S:M:L:XL</green> <orange>L:M</orange>
  • 向图像元素添加动态计数,例如<image1> <image2>

源代码:

<?xml version="1.0" encoding="utf-8"?>
<PRODUCTS>
 <PRODUCT>
  <CODE>19</CODE>
  <NAME>daisy</NAME>
  <MANUFACTURER>79</MANUFACTURER>
  <DESCRIPTION>t-shirt</DESCRIPTION>
  <SIZES></SIZES>
  <PRICE>33.33</PRICE>
  <PRICE_AKCIA>24.17</PRICE_AKCIA>
  <CATEGORY_ID>42</CATEGORY_ID>
  <CATEGORIES>
    <CATEGORY>clothes</CATEGORY>
    <CATEGORY>t-shirt</CATEGORY>
    <CATEGORY>latest</CATEGORY>
  </CATEGORIES>
  <COLORS>
   <COLOR>
    <NAME>green</NAME>
    <IMAGE>http://www.xyz.com/userfiles/daisy_green.png</IMAGE>
    <AVAILABLE_SIZES>
     <SIZE>S</SIZE>
     <SIZE>M</SIZE>
    </AVAILABLE_SIZES>
    <SIZES>
     <SIZE>S</SIZE>
     <SIZE>M</SIZE>
     <SIZE>L</SIZE>
     <SIZE>XL</SIZE>
    </SIZES>
   </COLOR>
   <COLOR>
    <NAME>orange</NAME>
    <IMAGE>http://www.xyz.com/userfiles/daisy_orange.png</IMAGE>
    <AVAILABLE_SIZES>
     <SIZE>L</SIZE>
     <SIZE>M</SIZE>
    </AVAILABLE_SIZES>
    <SIZES>
     <SIZE>S</SIZE>
     <SIZE>M</SIZE>
     <SIZE>L</SIZE>
     <SIZE>XL</SIZE>
    </SIZES>
   </COLOR>
  </COLORS>
 </PRODUCT>
</PRODUCTS>

xsl 样式表:

<?xml version="1.0" encoding="utf-8"?>
<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:template match="/">
    <xsl:element name="products">
        <xsl:apply-templates select="PRODUCTS/PRODUCT"/>
    </xsl:element>
</xsl:template>

<xsl:template match="PRODUCTS/PRODUCT"> 
    <xsl:element name="product">
        <xsl:element name="id">
            <xsl:value-of select="CODE"/>
        </xsl:element>
        <xsl:element name="name">
            <xsl:value-of select="NAME"/>
        </xsl:element>
        <xsl:element name="model">
            <xsl:value-of select="CODE"/>
        </xsl:element>
        <xsl:element name="manufacturer">
            <xsl:value-of select="MANUFACTURER"/>
        </xsl:element>
        <xsl:element name="category_id">
            <xsl:value-of select="CATEGORY_ID"/>
        </xsl:element>
        <xsl:apply-templates select="CATEGORIES"/>
        <xsl:element name="description">
            <xsl:value-of select="DESCRIPTION"/>
        </xsl:element>
        <xsl:element name="price">
            <xsl:value-of select="PRICE"/>
        </xsl:element>
        <xsl:element name="special">
            <xsl:value-of select="PRICE_AKCIA"/>
        </xsl:element>
        <xsl:apply-templates select="COLORS/COLOR"/>
        <xsl:apply-templates select="COLORS"/>
    </xsl:element>
</xsl:template>

<xsl:template match="CATEGORIES">
    <xsl:for-each select="CATEGORY">    
      <xsl:element name="category">
        <xsl:value-of select="."/>
      </xsl:element>
    </xsl:for-each>
</xsl:template>

<xsl:template match="COLORS">
    <xsl:for-each select="COLOR/NAME">    
      <xsl:variable name="color" select="." />
      <xsl:element name="{$color}">
        <xsl:apply-templates select="COLOR/AVAILABLE_SIZES"/>
      </xsl:element>
    </xsl:for-each>
</xsl:template>

<xsl:template match="COLORS/COLOR">
    <xsl:for-each select="IMAGE">    
      <xsl:element name="image">
        <xsl:value-of select="."/>
      </xsl:element>
    </xsl:for-each>
</xsl:template>

<xsl:template match="COLOR/AVAILABLE_SIZES">
    <xsl:for-each select="SIZE">    
      <xsl:value-of select="."/>:
    </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

结果:

<?xml version="1.0" encoding="UTF-8"?>
<products>
  <product>
    <id>19</id>
    <name>daisy</name>
    <model>19</model>
    <manufacturer>79</manufacturer>
    <category_id>42</category_id>
    <category>clothes</category>
    <category>t-shirt</category>
    <category>latest</category>
    <description>t-shirt</description>
    <price>33.33</price>
    <special>24.17</special>
    <image>http://www.xyz.com/userfiles/daisy_green.png</image>
    <image>http://www.xyz.com/userfiles/daisy_orange.png</image>
    <green/>
    <orange/>
  </product>
</products>
4

1 回答 1

0

如果要动态命名元素,可以使用属性值模板来指定元素名称。

所以,如果你想要category1category2等,而不仅仅是category你会这样做

 <xsl:element name="category{position()}">

花括号表示这是一个要计算的表达式。

但是,如果您直接使用图像代码执行此操作,您会看到它们都以 1 为后缀。

<xsl:template match="COLORS/COLOR">
    <xsl:for-each select="IMAGE">    
      <xsl:element name="image{position()}">
        <xsl:value-of select="."/>
      </xsl:element>
    </xsl:for-each>
</xsl:template>

这是因为您正在获取IMAGE元素在COLOR元素中的位置。你真的想要父COLOR元素的位置。相反,在这里匹配COLORS元素可能会更好,然后您可以获得COLOR元素的位置。

<xsl:template match="COLORS">
    <xsl:for-each select="COLOR">    
      <xsl:element name="image{position()}">
        <xsl:value-of select="IMAGE"/>
      </xsl:element>
    </xsl:for-each>
</xsl:template>

当然,这意味着您最终会得到两个匹配颜色的模板,因此您可能希望将它们组合起来。但是,另一个模板存在问题。您正在迭代COLOR/NAME,这意味着您将定位在循环内的NAME元素上。因此,当您尝试选择COLOR/AVAILABLE_SIZES时,它会在当前元素下方寻找它们,但它们不存在。你可能应该这样做

<xsl:template match="COLORS">
    <xsl:for-each select="COLOR">    
      <xsl:variable name="color" select="NAME" />
      <xsl:element name="{$color}">
        <xsl:apply-templates select="AVAILABLE_SIZES"/>
      </xsl:element>
    </xsl:for-each>

    <!-- Code to do images from above -->
</xsl:template>

还有几件事需要注意。如果你想要动态元素名称(如上所示),你只需要使用xsl:element ,否则直接输出元素。

此外,在许多情况下,您所做的只是将大写名称转换为小写。有一个通用模板可能会更简单

<xsl:template match="*">
   <xsl:element name="{translate(
         local-name(), 
         'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 
         'abcdefghijklmnopqrstuvwxyz')}">
      <xsl:apply-templates />
     </xsl:element>
</xsl:template>

这将减少您需要编写的代码。当您想将元素名称更改为完全不同的名称时,您只需要特定的模板。

尝试以下 XSLT

<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:template match="*">
      <xsl:element name="{translate(local-name(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')}">
         <xsl:apply-templates/>
      </xsl:element>
   </xsl:template>

   <xsl:template match="CODE">
      <id>
         <xsl:value-of select="."/>
      </id>
   </xsl:template>

   <xsl:template match="PRICE_AKCIA">
      <special>
         <xsl:value-of select="."/>
      </special>
   </xsl:template>

   <xsl:template match="CATEGORIES">
      <xsl:for-each select="CATEGORY">
         <xsl:element name="category{position()}">
            <xsl:value-of select="."/>
         </xsl:element>
      </xsl:for-each>
   </xsl:template>

   <xsl:template match="COLORS">
      <xsl:for-each select="COLOR">
         <xsl:variable name="color" select="NAME"/>
         <xsl:element name="{$color}">
            <xsl:apply-templates select="AVAILABLE_SIZES"/>
         </xsl:element>
      </xsl:for-each>
      <xsl:for-each select="COLOR">
         <xsl:element name="image{position()}">
            <xsl:value-of select="IMAGE"/>
         </xsl:element>
      </xsl:for-each>
   </xsl:template>

   <xsl:template match="AVAILABLE_SIZES">
      <xsl:for-each select="SIZE">
         <xsl:if test="position() > 1">:</xsl:if>
         <xsl:value-of select="."/>
      </xsl:for-each>
   </xsl:template>
</xsl:stylesheet>

应用于您的示例 XML 时,将输出以下内容

<products>
   <product>
      <id>19</id>
      <name>daisy</name>
      <manufacturer>79</manufacturer>
      <description>t-shirt</description>
      <sizes/>
      <price>33.33</price>
      <special>24.17</special>
      <category_id>42</category_id>
      <category1>clothes</category1>
      <category2>t-shirt</category2>
      <category3>latest</category3>
      <green>S:M</green>
      <orange>L:M</orange>
      <image1>http://www.xyz.com/userfiles/daisy_green.png</image1>
      <image2>http://www.xyz.com/userfiles/daisy_orange.png</image2>
   </product>
</products>
于 2012-11-05T09:32:35.117 回答