以下是我的XML文件的摘录,每个产品都是个人<SHOPITEM>
:
<?xml version="1.0" encoding="UTF-8"?>
<SHOP>
<SHOPITEM>
<CATEGORY>Full</CATEGORY>
<WHEEL>27.5</WHEEL>
<FRAMESIZE>MD</FRAMESIZE>
<CODE>032,00</CODE>
<PRODUCT>POINT</PRODUCT>
<COLOR>black / white</COLOR>
<NOTE>Available 15.2.2015</NOTE>
<URL></URL>
<IMGURL1></IMGURL1>
<IMGURL2></IMGURL2>
<IMGURL3></IMGURL3>
<PRICE>3199.99</PRICE>
<CURRENCY>EUR</CURRENCY>
<YEAR>2015</YEAR>
<AVAILABLE>NO</AVAILABLE>
</SHOPITEM>
<SHOPITEM>
<CATEGORY>Full</CATEGORY>
<WHEEL>27.5</WHEEL>
<FRAMESIZE>MD</FRAMESIZE>
<CODE>032,99</CODE>
<PRODUCT>POINT</PRODUCT>
<COLOR>red / green</COLOR>
<NOTE>Available 15.2.2015</NOTE>
<URL></URL>
<IMGURL1></IMGURL1>
<IMGURL2></IMGURL2>
<IMGURL3></IMGURL3>
<PRICE>3199.99</PRICE>
<CURRENCY>EUR</CURRENCY>
<YEAR>2015</YEAR>
<AVAILABLE>NO</AVAILABLE>
</SHOPITEM>
<SHOPITEM>
<CATEGORY>Full</CATEGORY>
<WHEEL>27.5</WHEEL>
<FRAMESIZE>LG</FRAMESIZE>
<CODE>032,01</CODE>
<PRODUCT>POINT</PRODUCT>
<COLOR>black / white</COLOR>
<NOTE>Available 15.2.2015</NOTE>
<URL></URL>
<IMGURL1></IMGURL1>
<IMGURL2></IMGURL2>
<IMGURL3></IMGURL3>
<PRICE>3199.99</PRICE>
<CURRENCY>EUR</CURRENCY>
<YEAR>2015</YEAR>
<AVAILABLE>NO</AVAILABLE>
</SHOPITEM>
</SHOP>
可以在同一<PRODUCT>
上对产品选项进行分组,如下所示:
<SHOPITEM>
<CATEGORY>Full</CATEGORY>
<WHEEL>27.5</WHEEL>
<FRAMESIZE>LG</FRAMESIZE>
<CODE>032,01</CODE>
<PRODUCT>POINT</PRODUCT>
<COLOR>black / white</COLOR>
<NOTE>Available 15.2.2015</NOTE>
<URL></URL>
<IMGURL1></IMGURL1>
<IMGURL2></IMGURL2>
<IMGURL3></IMGURL3>
<PRICE>3199.99</PRICE>
<CURRENCY>EUR</CURRENCY>
<YEAR>2015</YEAR>
<AVAILABLE>NO</AVAILABLE>
<PRODUCT_VARIANT id="2">
<COLOR>red / green</COLOR>
<FRAMESIZE>MD</FRAMESIZE>
<CODE>032,99</CODE>
<IMGURL1></IMGURL1>
<IMGURL2></IMGURL2>
<IMGURL3></IMGURL3>
<AVAILABLE>NO</AVAILABLE>
<NOTE>Available 15.2.2015</NOTE>
</PRODUCT_VARIANT>
<PRODUCT_VARIANT id="3">
<COLOR>black / white</COLOR>
<FRAMESIZE>LG</FRAMESIZE>
<CODE>032,01</CODE>
<IMGURL1></IMGURL1>
<IMGURL2></IMGURL2>
<IMGURL3></IMGURL3>
<AVAILABLE>NO</AVAILABLE>
<NOTE>Available 15.2.2015</NOTE>
</PRODUCT_VARIANT>
</SHOPITEM>
答案 0 :(得分:3)
注意:这是基于假设应该基于<PRODUCT>
子节点的相同值对商店项目进行分组。如果必须比较其他节点值,请将其添加到问题中。
以下XSLT
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" doctype-public="XSLT-compat"
omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="SHOPITEM[not(PRODUCT=preceding-sibling::SHOPITEM/PRODUCT)]">
<xsl:variable name="currentProduct" select="PRODUCT"/>
<xsl:copy>
<xsl:apply-templates/>
<xsl:if test="following-sibling::SHOPITEM[PRODUCT=$currentProduct]">
<xsl:apply-templates select="following-sibling::SHOPITEM
[PRODUCT=$currentProduct]" mode="variant"/>
</xsl:if>
</xsl:copy>
</xsl:template>
<xsl:template match="SHOPITEM" mode="variant">
<xsl:variable name="currentProduct" select="PRODUCT"/>
<PRODUCT_VARIANT>
<xsl:attribute name="id">
<xsl:value-of select="count(preceding-sibling::SHOPITEM/PRODUCT
[.=$currentProduct]) + 1"/>
</xsl:attribute>
<xsl:apply-templates/>
</PRODUCT_VARIANT>
</xsl:template>
<xsl:template match="SHOPITEM[PRODUCT=preceding-sibling::SHOPITEM/PRODUCT]"/>
</xsl:transform>
当应用于您的输入时,XML会生成所需的输出。
模板
<xsl:template match="SHOPITEM[not(PRODUCT=preceding-sibling::SHOPITEM/PRODUCT)]">
复制具有SHOPITEM
子节点的所有PRODUCT
个节点,这些子节点不是前一个shopitems的子节点。如果此SHOPITEM
跟随同一PRODUCT
<xsl:if test="following-sibling::SHOPITEM[PRODUCT=$currentProduct]">
使用
将它们复制为变体<xsl:template match="SHOPITEM" mode="variant">
此模板会创建元素<PRODUCT_VARIANT>
,并将所有在先产品的计数设置为属性id
,其值与当前SHOPITEM
+ 1的产品相同:
<xsl:value-of select="count(preceding-sibling::SHOPITEM/PRODUCT
[.=$currentProduct]) + 1"/>
模板匹配
<xsl:template match="SHOPITEM[PRODUCT=preceding-sibling::SHOPITEM/PRODUCT]"/>
为空,并删除已编写为变体的SHOPITEM
个节点。
更新:对于评论中的问题,是否可以将CODE
添加为PRIMARY_CODE
到每个变体 - 调整后的XSLT
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" doctype-public="XSLT-compat"
omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="SHOPITEM[not(PRODUCT=preceding-sibling::SHOPITEM/PRODUCT)]">
<xsl:variable name="currentProduct" select="PRODUCT"/>
<xsl:variable name="currentCode" select="CODE"/>
<xsl:copy>
<xsl:apply-templates/>
<xsl:if test="following-sibling::SHOPITEM[PRODUCT=$currentProduct]">
<xsl:apply-templates select="following-sibling::SHOPITEM
[PRODUCT=$currentProduct]" mode="variant">
<xsl:with-param name="code" select="$currentCode"/>
</xsl:apply-templates>
</xsl:if>
</xsl:copy>
</xsl:template>
<xsl:template match="SHOPITEM" mode="variant">
<xsl:param name="code"/>
<xsl:variable name="currentProduct" select="PRODUCT"/>
<PRODUCT_VARIANT>
<xsl:attribute name="id">
<xsl:value-of select="count(preceding-sibling::SHOPITEM/PRODUCT
[.=$currentProduct]) + 1"/>
</xsl:attribute>
<PRIMARY_CODE>
<xsl:value-of select="$code"/>
</PRIMARY_CODE>
<xsl:apply-templates/>
</PRODUCT_VARIANT>
</xsl:template>
<xsl:template match="SHOPITEM[PRODUCT=preceding-sibling::SHOPITEM/PRODUCT]"/>
</xsl:transform>
生成所需的输出,只是相关部分:
<PRODUCT_VARIANT id="2">
<PRIMARY_CODE>032,00</PRIMARY_CODE>
<CATEGORY>Full</CATEGORY>
...
调整只是在匹配<xsl:variable name="currentCode" select="CODE"/>
的模板中设置SHOPITEM
,然后将mode="variant"
作为参数应用于模板currentCode
:
<xsl:apply-templates select="following-sibling::SHOPITEM
[PRODUCT=$currentProduct]" mode="variant">
<xsl:with-param name="code" select="$currentCode"/>
</xsl:apply-templates>
在<xsl:template match="SHOPITEM" mode="variant">
中,参数添加为<xsl:param name="code"/>
,并简单地写为
<PRIMARY_CODE><xsl:value-of select="$code"/></PRIMARY_CODE>
在<PRODUCT_VARIANT>
之后。
为方便起见,我将其保存在此处:http://xsltransform.net/bFDb2Cd
答案 1 :(得分:2)
这是另一个使用xsl:key
...
XML输入
<SHOP>
<SHOPITEM>
<CATEGORY>Full</CATEGORY>
<WHEEL>27.5</WHEEL>
<FRAMESIZE>MD</FRAMESIZE>
<CODE>032,00</CODE>
<PRODUCT>POINT</PRODUCT>
<COLOR>black / white</COLOR>
<NOTE>Available 15.2.2015</NOTE>
<URL></URL>
<IMGURL1></IMGURL1>
<IMGURL2></IMGURL2>
<IMGURL3></IMGURL3>
<PRICE>3199.99</PRICE>
<CURRENCY>EUR</CURRENCY>
<YEAR>2015</YEAR>
<AVAILABLE>NO</AVAILABLE>
</SHOPITEM>
<SHOPITEM>
<CATEGORY>Full</CATEGORY>
<WHEEL>27.5</WHEEL>
<FRAMESIZE>MD</FRAMESIZE>
<CODE>032,99</CODE>
<PRODUCT>POINT</PRODUCT>
<COLOR>red / green</COLOR>
<NOTE>Available 15.2.2015</NOTE>
<URL></URL>
<IMGURL1></IMGURL1>
<IMGURL2></IMGURL2>
<IMGURL3></IMGURL3>
<PRICE>3199.99</PRICE>
<CURRENCY>EUR</CURRENCY>
<YEAR>2015</YEAR>
<AVAILABLE>NO</AVAILABLE>
</SHOPITEM>
<SHOPITEM>
<CATEGORY>Full</CATEGORY>
<WHEEL>27.5</WHEEL>
<FRAMESIZE>LG</FRAMESIZE>
<CODE>032,01</CODE>
<PRODUCT>POINT</PRODUCT>
<COLOR>black / white</COLOR>
<NOTE>Available 15.2.2015</NOTE>
<URL></URL>
<IMGURL1></IMGURL1>
<IMGURL2></IMGURL2>
<IMGURL3></IMGURL3>
<PRICE>3199.99</PRICE>
<CURRENCY>EUR</CURRENCY>
<YEAR>2015</YEAR>
<AVAILABLE>NO</AVAILABLE>
</SHOPITEM>
</SHOP>
XSLT 1.0
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="products" match="SHOPITEM" use="PRODUCT"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/SHOP">
<xsl:copy>
<xsl:for-each select="SHOPITEM[generate-id() = generate-id(key('products',PRODUCT)[1])]">
<SHOPITEM>
<xsl:for-each select="/*/SHOPITEM[key('products',PRODUCT)]">
<xsl:apply-templates select="."/>
</xsl:for-each>
</SHOPITEM>
</xsl:for-each>
</xsl:copy>
</xsl:template>
<xsl:template match="SHOPITEM[position()=1]">
<xsl:apply-templates select="@*|node()"/>
</xsl:template>
<xsl:template match="SHOPITEM">
<PRODUCT_VARIANT>
<xsl:attribute name="id">
<xsl:number/>
</xsl:attribute>
<xsl:apply-templates select="@*|node()"/>
</PRODUCT_VARIANT>
</xsl:template>
</xsl:stylesheet>
XML输出
<SHOP>
<SHOPITEM>
<CATEGORY>Full</CATEGORY>
<WHEEL>27.5</WHEEL>
<FRAMESIZE>MD</FRAMESIZE>
<CODE>032,00</CODE>
<PRODUCT>POINT</PRODUCT>
<COLOR>black / white</COLOR>
<NOTE>Available 15.2.2015</NOTE>
<URL/>
<IMGURL1/>
<IMGURL2/>
<IMGURL3/>
<PRICE>3199.99</PRICE>
<CURRENCY>EUR</CURRENCY>
<YEAR>2015</YEAR>
<AVAILABLE>NO</AVAILABLE>
<PRODUCT_VARIANT id="2">
<CATEGORY>Full</CATEGORY>
<WHEEL>27.5</WHEEL>
<FRAMESIZE>MD</FRAMESIZE>
<CODE>032,99</CODE>
<PRODUCT>POINT</PRODUCT>
<COLOR>red / green</COLOR>
<NOTE>Available 15.2.2015</NOTE>
<URL/>
<IMGURL1/>
<IMGURL2/>
<IMGURL3/>
<PRICE>3199.99</PRICE>
<CURRENCY>EUR</CURRENCY>
<YEAR>2015</YEAR>
<AVAILABLE>NO</AVAILABLE>
</PRODUCT_VARIANT>
<PRODUCT_VARIANT id="3">
<CATEGORY>Full</CATEGORY>
<WHEEL>27.5</WHEEL>
<FRAMESIZE>LG</FRAMESIZE>
<CODE>032,01</CODE>
<PRODUCT>POINT</PRODUCT>
<COLOR>black / white</COLOR>
<NOTE>Available 15.2.2015</NOTE>
<URL/>
<IMGURL1/>
<IMGURL2/>
<IMGURL3/>
<PRICE>3199.99</PRICE>
<CURRENCY>EUR</CURRENCY>
<YEAR>2015</YEAR>
<AVAILABLE>NO</AVAILABLE>
</PRODUCT_VARIANT>
</SHOPITEM>
</SHOP>
这与您想要的输出不同,因为它包含变体的SHOPITEM
的所有原始子项。这是一个修改后的版本,仅保留与该组中第一个SHOPITEM
不同的元素:
XSLT 1.0
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="products" match="SHOPITEM" use="PRODUCT"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/SHOP">
<xsl:copy>
<xsl:for-each select="SHOPITEM[generate-id() = generate-id(key('products',PRODUCT)[1])]">
<SHOPITEM>
<xsl:for-each select="/*/SHOPITEM[key('products',PRODUCT)]">
<xsl:apply-templates select="."/>
</xsl:for-each>
</SHOPITEM>
</xsl:for-each>
</xsl:copy>
</xsl:template>
<xsl:template match="SHOPITEM[position()=1]">
<xsl:apply-templates select="@*|node()"/>
</xsl:template>
<xsl:template match="SHOPITEM">
<PRODUCT_VARIANT>
<xsl:attribute name="id">
<xsl:number/>
</xsl:attribute>
<xsl:apply-templates select="*" mode="variant"/>
</PRODUCT_VARIANT>
</xsl:template>
<xsl:template match="SHOPITEM/*" mode="variant">
<xsl:if test="not(key('products',../PRODUCT)[1]/*[name()=name(current())]=.)">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
XML输出
<SHOP>
<SHOPITEM>
<CATEGORY>Full</CATEGORY>
<WHEEL>27.5</WHEEL>
<FRAMESIZE>MD</FRAMESIZE>
<CODE>032,00</CODE>
<PRODUCT>POINT</PRODUCT>
<COLOR>black / white</COLOR>
<NOTE>Available 15.2.2015</NOTE>
<URL/>
<IMGURL1/>
<IMGURL2/>
<IMGURL3/>
<PRICE>3199.99</PRICE>
<CURRENCY>EUR</CURRENCY>
<YEAR>2015</YEAR>
<AVAILABLE>NO</AVAILABLE>
<PRODUCT_VARIANT id="2">
<CODE>032,99</CODE>
<COLOR>red / green</COLOR>
</PRODUCT_VARIANT>
<PRODUCT_VARIANT id="3">
<FRAMESIZE>LG</FRAMESIZE>
<CODE>032,01</CODE>
</PRODUCT_VARIANT>
</SHOPITEM>
</SHOP>