Re-order XML elements in a specific way using XSLT [closed]

狂风中的少年 提交于 2020-01-03 06:59:25

问题


I have two XSL variables. 1.ProductID

  <prdid>
    <id>8143794</id>
    <id>8143793</id>
    <id>8142229</id>
    <id>8143796</id>
  </prdid>

2.Productxml

    <root>
  <product>
    <estocklevel>0</estocklevel>
    <id>8142229</id>
    <isp_brand extra="isp_brand"></isp_brand>
    <isp_produktserie extra="isp_produktserie"></isp_produktserie>
    <isp_model extra="isp_model"></isp_model>
  </product>
  <product>
    <estocklevel>0</estocklevel>
    <id>8143793</id>
    <isp_brand extra="isp_brand">Leitz</isp_brand>
    <isp_produktserie extra="isp_produktserie">180</isp_produktserie>
    <isp_model extra="isp_model">Bred</isp_model>
  </product> 
  <product>
    <estocklevel>0</estocklevel>
    <id>8143794</id>
    <isp_brand extra="isp_brand">Leitz</isp_brand>
    <isp_produktserie extra="isp_produktserie">180</isp_produktserie>
    <isp_model extra="isp_model">Smal</isp_model>
  </product>
  <product>
    <id>8143796</id>
    <isp_brand extra="isp_brand">Leitz</isp_brand>
    <isp_produktserie extra="isp_produktserie">180</isp_produktserie>
    <isp_model extra="isp_model">Smal</isp_model>
  </product>
</root>

Now what i want is, in a for loop i want to get each products in productxml ,in an order from prdid XML like

 <xsl:for-each select="prdid/id">
        <!--i want to get a product node from productxml here which got same id of that in this for loop -->
      <xsl:value-of select="productxml/id"/>
    </xsl:for-each>

回答1:


This transformation is short and efficient:

<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:variable name="vProds" select=
   "document('file:///c:/temp/delete/products.xml')"/>

 <xsl:key name="kProdById" match="product" use="id"/>

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

 <xsl:template match="id">
  <xsl:variable name="vId" select="."/>
  <xsl:for-each select="$vProds">
   <xsl:copy-of select="key('kProdById', $vId)"/>
  </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

When it is applied on the provided "prdid" XML document:

<prdid>
    <id>8143794</id>
    <id>8143793</id>
    <id>8142229</id>
    <id>8143796</id>
</prdid>

and the second provided document is contained in the file: c:\temp\delete\products.xml:

<root>
    <product>
        <estocklevel>0</estocklevel>
        <id>8142229</id>
        <isp_brand extra="isp_brand"></isp_brand>
        <isp_produktserie extra="isp_produktserie"></isp_produktserie>
        <isp_model extra="isp_model"></isp_model>
    </product>
    <product>
        <estocklevel>0</estocklevel>
        <id>8143793</id>
        <isp_brand extra="isp_brand">Leitz</isp_brand>
        <isp_produktserie extra="isp_produktserie">180</isp_produktserie>
        <isp_model extra="isp_model">Bred</isp_model>
    </product>
    <product>
        <estocklevel>0</estocklevel>
        <id>8143794</id>
        <isp_brand extra="isp_brand">Leitz</isp_brand>
        <isp_produktserie extra="isp_produktserie">180</isp_produktserie>
        <isp_model extra="isp_model">Smal</isp_model>
    </product>
    <product>
        <id>8143796</id>
        <isp_brand extra="isp_brand">Leitz</isp_brand>
        <isp_produktserie extra="isp_produktserie">180</isp_produktserie>
        <isp_model extra="isp_model">Smal</isp_model>
    </product>
</root>

the wanted, correct result is produced:

<root>
   <product>
      <estocklevel>0</estocklevel>
      <id>8143794</id>
      <isp_brand extra="isp_brand">Leitz</isp_brand>
      <isp_produktserie extra="isp_produktserie">180</isp_produktserie>
      <isp_model extra="isp_model">Smal</isp_model>
   </product>
   <product>
      <estocklevel>0</estocklevel>
      <id>8143793</id>
      <isp_brand extra="isp_brand">Leitz</isp_brand>
      <isp_produktserie extra="isp_produktserie">180</isp_produktserie>
      <isp_model extra="isp_model">Bred</isp_model>
   </product>
   <product>
      <estocklevel>0</estocklevel>
      <id>8142229</id>
      <isp_brand extra="isp_brand"/>
      <isp_produktserie extra="isp_produktserie"/>
      <isp_model extra="isp_model"/>
   </product>
   <product>
      <id>8143796</id>
      <isp_brand extra="isp_brand">Leitz</isp_brand>
      <isp_produktserie extra="isp_produktserie">180</isp_produktserie>
      <isp_model extra="isp_model">Smal</isp_model>
   </product>
</root>

Explanation:

Proper use of keys.

This demonstrates how to use with XSLT 1.0 a value from one XML document as a key for nodes in another XML document.




回答2:


I'm assuming "Productxml" is your input XML file.

Stylesheet

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

  <!--
  The order in which you want to process the <product> elements. You could also
  have this in a separate file if you want, and change the document() function
  below to point to that file instead.
  -->
  <my:prdid>
    <id>8143794</id>
    <id>8143793</id>
    <id>8142229</id>
    <id>8143796</id>
  </my:prdid>

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

  <xsl:template match="root">
    <!-- Save reference to the nodeset that contains all <product> children -->
    <xsl:variable name="products" select="product"/>

    <xsl:copy>
      <!--
      For each <id> element in the <my:prdid> element (document('') refers to
      the current stylesheet)...
      -->
      <xsl:for-each select="document('')/*/my:prdid/id">
        <!--
        ...apply the <product> element that has the same id value as this <id>
        element
        -->
        <xsl:apply-templates select="$products[id = current()]"/>
      </xsl:for-each>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

Input

<root>
  <product>
    <estocklevel>0</estocklevel>
    <id>8142229</id>
    <isp_brand extra="isp_brand"></isp_brand>
    <isp_produktserie extra="isp_produktserie"></isp_produktserie>
    <isp_model extra="isp_model"></isp_model>
  </product>
  <product>
    <estocklevel>0</estocklevel>
    <id>8143793</id>
    <isp_brand extra="isp_brand">Leitz</isp_brand>
    <isp_produktserie extra="isp_produktserie">180</isp_produktserie>
    <isp_model extra="isp_model">Bred</isp_model>
  </product> 
  <product>
    <estocklevel>0</estocklevel>
    <id>8143794</id>
    <isp_brand extra="isp_brand">Leitz</isp_brand>
    <isp_produktserie extra="isp_produktserie">180</isp_produktserie>
    <isp_model extra="isp_model">Smal</isp_model>
  </product>
  <product>
    <id>8143796</id>
    <isp_brand extra="isp_brand">Leitz</isp_brand>
    <isp_produktserie extra="isp_produktserie">180</isp_produktserie>
    <isp_model extra="isp_model">Smal</isp_model>
  </product>
</root>

Output

<root>
  <product>
    <estocklevel>0</estocklevel>
    <id>8143794</id>
    <isp_brand extra="isp_brand">Leitz</isp_brand>
    <isp_produktserie extra="isp_produktserie">180</isp_produktserie>
    <isp_model extra="isp_model">Smal</isp_model>
  </product>
  <product>
    <estocklevel>0</estocklevel>
    <id>8143793</id>
    <isp_brand extra="isp_brand">Leitz</isp_brand>
    <isp_produktserie extra="isp_produktserie">180</isp_produktserie>
    <isp_model extra="isp_model">Bred</isp_model>
  </product>
  <product>
    <estocklevel>0</estocklevel>
    <id>8142229</id>
    <isp_brand extra="isp_brand"/>
    <isp_produktserie extra="isp_produktserie"/>
    <isp_model extra="isp_model"/>
  </product>
  <product>
    <id>8143796</id>
    <isp_brand extra="isp_brand">Leitz</isp_brand>
    <isp_produktserie extra="isp_produktserie">180</isp_produktserie>
    <isp_model extra="isp_model">Smal</isp_model>
  </product>
</root>



回答3:


xsl:sort should be what you need. Take a look here:

http://www.w3schools.com/xsl/el_sort.asp#gsc.tab=0

Edit 1: This should work

<xsl:for-each select="//prdid/id">
  <xsl:call-template name="sortedId">
    <xsl:with-param name="id" select="."></xsl:with-param>
  </xsl:call-template>
</xsl:for-each>    


<xsl:template name="sortedId" >
    <xsl:param name="id"></xsl:param>
    <xsl:apply-templates select="//product[id=$id]" />
</xsl:template>

<xsl:template match="product">
    <xsl:copy-of select="." />
</xsl:template>


来源:https://stackoverflow.com/questions/15759871/re-order-xml-elements-in-a-specific-way-using-xslt

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!