问题
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