Identity transformation in XSLT

2019-02-19 04:09发布

I have this source XML:

<?xml version="1.0"?>
<root>
   <item1>
      <name>test</name>
      <price>160</price>
      <stock>4</stock>
      <country>Belgium</country>
   </item1>
   <item2>
      <name>Alfa</name>

      <price>140</price>

      <stock>3</stock>

      <country>Turkey</country>
   </item2>
   <item3>
      <name>Beta</name>

      <price>110</price>

      <stock>48</stock>

      <country>Holland</country>
   </item3>
   <product id="p1">
      <name>Delta</name>

      <price>800</price>

      <stock>4</stock>

      <country>Denmark</country>
   </product>
   <product id="p2">
      <name>Golf</name>

      <price>1000</price>

      <stock>5</stock>

      <country>Germany</country>
   </product>
   <product id="p3">
      <name>Alfa</name>

      <price>1200</price>

      <stock>19</stock>

      <country>Germany</country>
   </product>
   <product id="p4">
      <name>Foxtrot</name>

      <price>1500</price>

      <stock>5</stock>

      <country>Australia</country>
   </product>
   <product id="p5">
      <name>Tango</name>

      <price>1225</price>

      <stock>3</stock>

      <country>Japan</country>
   </product>
</root>

And I want it to look like this:

<?xml version="1.0"?>
<root>
   <action>
      <name>test</name>

      <price>160</price>

      <stock>4</stock>

      <country>Belgium</country>
   </action>
   <action>
      <name>Alfa</name>

      <price>140</price>

      <stock>3</stock>

      <country>Turkey</country>
   </action>
   <action>
      <name>Beta</name>

      <price>110</price>

      <stock>48</stock>

      <country>Holland</country>
   </action>
   <action>
      <name>Delta</name>

      <price>800</price>

      <stock>4</stock>

      <country>Denmark</country>
   </action>
   <action>
      <name>Golf</name>

      <price>1000</price>

      <stock>5</stock>

      <country>Germany</country>
   </action>
   <action>
      <name>Alfa</name>

      <price>1200</price>

      <stock>19</stock>

      <country>Germany</country>
   </action>
   <action>
      <name>Foxtrot</name>

      <price>1500</price>

      <stock>5</stock>

      <country>Australia</country>
   </action>
   <action>
      <name>Tango</name>

      <price>1225</price>

      <stock>3</stock>

      <country>Japan</country>
   </action>
</root>

So the <item1> to <item3> turn into

<action>

And the <product> loses its attribute, and also turns into

<action>

Can somebody show me how to do this with XSLT? Because I have 2 different XSL's now. And I want to combine them to create just one XSL.

Thanks in advance

标签: xml xslt
3条回答
Luminary・发光体
2楼-- · 2019-02-19 04:36

Sounds easy:

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="1.0">

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

  <xsl:template match="root/*">
    <action>
      <xsl:apply-templates/>
    </action>
  </xsl:template>

</xsl:stylesheet>

If you want us to combine your existing code you need to post it.

查看更多
虎瘦雄心在
3楼-- · 2019-02-19 04:38

This transformation:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

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

 <xsl:template match="product|*[starts-with(name(), 'item')]">
  <action>
   <xsl:apply-templates select="node()|@*"/>
  </action>
 </xsl:template>

 <xsl:template match="product/@id"/>
</xsl:stylesheet>

when applied on the provided XML document:

<root>
    <item1>
        <name>test</name>
        <price>160</price>
        <stock>4</stock>
        <country>Belgium</country>
    </item1>
    <item2>
        <name>Alfa</name>
        <price>140</price>
        <stock>3</stock>
        <country>Turkey</country>
    </item2>
    <item3>
        <name>Beta</name>
        <price>110</price>
        <stock>48</stock>
        <country>Holland</country>
    </item3>
    <product id="p1">
        <name>Delta</name>
        <price>800</price>
        <stock>4</stock>
        <country>Denmark</country>
    </product>
    <product id="p2">
        <name>Golf</name>
        <price>1000</price>
        <stock>5</stock>
        <country>Germany</country>
    </product>
    <product id="p3">
        <name>Alfa</name>
        <price>1200</price>
        <stock>19</stock>
        <country>Germany</country>
    </product>
    <product id="p4">
        <name>Foxtrot</name>
        <price>1500</price>
        <stock>5</stock>
        <country>Australia</country>
    </product>
    <product id="p5">
        <name>Tango</name>
        <price>1225</price>
        <stock>3</stock>
        <country>Japan</country>
    </product>
</root>

produces the wanted, correct result:

<root>
   <action>
      <name>test</name>
      <price>160</price>
      <stock>4</stock>
      <country>Belgium</country>
   </action>
   <action>
      <name>Alfa</name>
      <price>140</price>
      <stock>3</stock>
      <country>Turkey</country>
   </action>
   <action>
      <name>Beta</name>
      <price>110</price>
      <stock>48</stock>
      <country>Holland</country>
   </action>
   <action>
      <name>Delta</name>
      <price>800</price>
      <stock>4</stock>
      <country>Denmark</country>
   </action>
   <action>
      <name>Golf</name>
      <price>1000</price>
      <stock>5</stock>
      <country>Germany</country>
   </action>
   <action>
      <name>Alfa</name>
      <price>1200</price>
      <stock>19</stock>
      <country>Germany</country>
   </action>
   <action>
      <name>Foxtrot</name>
      <price>1500</price>
      <stock>5</stock>
      <country>Australia</country>
   </action>
   <action>
      <name>Tango</name>
      <price>1225</price>
      <stock>3</stock>
      <country>Japan</country>
   </action>
</root>

Explanation:

  1. The identity rule copies every node "as-is".

  2. We have two templates overriding the identity rule. The first template matches any product or any element whose name starts with the string item. It effectively "renames" the matched element to action by creating and outputting an action element.

  3. The second overriding template matches any id attribute of any product element. This template has no body, which effectively "deletes" the matched attribute -- it is not copied/recreated in the output.

查看更多
家丑人穷心不美
4楼-- · 2019-02-19 04:46

You could also just step through it and built it however you like. Ex:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" omit-xml-declaration="yes" indent="no" />

    <xsl:template match="/root">
        <xsl:element name="root">
            <xsl:for-each select="node()">
                <xsl:element name="action">
                    <xsl:element name="name"><xsl:value-of select="name"/></xsl:element>
                    <xsl:element name="price"><xsl:value-of select="price"/></xsl:element>
                    <xsl:element name="stock"><xsl:value-of select="stock"/></xsl:element>
                    <xsl:element name="country"><xsl:value-of select="country"/></xsl:element>
                </xsl:element>
            </xsl:for-each>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>
查看更多
登录 后发表回答