XSLT 1.0 - 使用 Vanilla XSLT 1.0 或 PHP XSLT 的节点中值唯一性的输出计数 [英] XSLT 1.0 - Output Count of Value Uniqueness in a Node with Vanilla XSLT 1.0 or PHP XSLT

查看:24
本文介绍了XSLT 1.0 - 使用 Vanilla XSLT 1.0 或 PHP XSLT 的节点中值唯一性的输出计数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的 XML 数据中有一个节点,该节点名为该节点,该节点包含一个唯一值,例如 45678.如果在完整数据中多次找到 45678 (1),我只想包含此节点的数据,通过 XSLT放.最终结果可以修改现有节点,或创建一个名为 的新节点.该数据的最终结果创建了有孩子的父母".产品.productId 值将所有相似的产品组合在一起,问题是有时只有 1 个产品具有该键,我不应该创建父产品.

I have a node in my XML data named this node contains a unique value, say 45678. Via XSLT, I'd like to only include this node's data, if 45678 is found more than once (1) in the complete data set. The end result can modify the existing node, or create a new one called . The end result of this data creates "Parent with children" products. The productId value groups all similar products together, the problem, is that sometimes there is only 1 product with that key, and I shouldn't create a parent product.

重要说明:为什么我这么挣扎,第一,我还是 XSL 的新手,第二,当前版本的引擎不允许我使用 EXSLT,但看起来我可以使用 PHP如有必要.

IMPORTANT NOTE: Why I'm struggling so much, is 1st, I'm still brand new to XSL, and second, the current version of the engine does not allow me to use EXSLT, but it appears I can use PHP if necessary.

样本数据集

<productId>0243176820</productId> 你可以看到这个值被多次使用,在这种情况下它应该包含在结果数据中,1136194258<;/productId> 但这个只包含一次.

<productId>0243176820</productId> This value you can see is used multiple times, and in this case it should be included in the result data, <productId>1136194258</productId> but this one is only included once.

以下示例数据

<root>
  <part>
    <partNumber>06013464</partNumber>
    <punctuatedPartNumber>0601-3464</punctuatedPartNumber>
    <partStatusDescription>DISCONTINUED</partStatusDescription>
    <partDescription>Flat Black 18" Handlebar</partDescription>
    <unitOfMeasure>Each</unitOfMeasure>
    <brandName>LA CHOPPERS</brandName>
    <supplierNumber>LA-7321-18M</supplierNumber>
    <specialInstructions/>
    <baseDealerPrice>185.0000</baseDealerPrice>
    <yourDealerPrice>185.0000</yourDealerPrice>
    <baseRetailPrice>272.9500</baseRetailPrice>
    <originalRetailPrice>272.9500</originalRetailPrice>
    <partImage>http://asset.lemansnet.com/z/LzgvQS80LzhBNDg5QjE2LUNEQkMtNDAzMC04NkE0LTlEQjE1MDdGRDYzMQ==</partImage>
    <productId>1136194258</productId>
    <productName>1-1/4" Touring Ape Hanger Handlebar</productName>
  </part>
  <part>
    <partNumber>06012660</partNumber>
    <punctuatedPartNumber>0601-2660</punctuatedPartNumber>
    <partStatusDescription>STANDARD</partStatusDescription>
    <partDescription>Black 10" Handlebar</partDescription>
    <unitOfMeasure>Each</unitOfMeasure>
    <brandName>LA CHOPPERS</brandName>
    <supplierNumber>LA-7321-10B</supplierNumber>
    <specialInstructions/>
    <baseDealerPrice>185.0000</baseDealerPrice>
    <yourDealerPrice>185.0000</yourDealerPrice>
    <baseRetailPrice>272.9500</baseRetailPrice>
    <originalRetailPrice>272.9500</originalRetailPrice>
    <partImage>http://asset.lemansnet.com/z/LzkvMC9DLzkwQzQ2MjZGLTQyOEItNDNGRi1CQjYwLTNBREMyOUM1REU4MQ==</partImage>
    <productId>0243176820</productId>
    <productName>1-1/4" Touring Ape Hanger Handlebar</productName>
  </part>
  <part>
    <partNumber>06012663</partNumber>
    <punctuatedPartNumber>0601-2663</punctuatedPartNumber>
    <partStatusDescription>STANDARD</partStatusDescription>
    <partDescription>Chrome 14" Handlebar</partDescription>
    <unitOfMeasure>Each</unitOfMeasure>
    <brandName>LA CHOPPERS</brandName>
    <supplierNumber>LA-7321-14</supplierNumber>
    <specialInstructions/>
    <baseDealerPrice>185.0000</baseDealerPrice>
    <yourDealerPrice>185.0000</yourDealerPrice>
    <baseRetailPrice>272.9500</baseRetailPrice>
    <originalRetailPrice>272.9500</originalRetailPrice>
    <partImage>http://asset.lemansnet.com/z/LzcvNC81Lzc0NUE3OUM4LTBERDAtNDQ3NS1CMEFBLUVBMDUyRkUzN0Q5OA==</partImage>
    <productId>0243176820</productId>
    <productName>1-1/4" Touring Ape Hanger Handlebar</productName>
  </part>
  <part>
    <partNumber>06011482</partNumber>
    <punctuatedPartNumber>0601-1482</punctuatedPartNumber>
    <partStatusDescription>STANDARD</partStatusDescription>
    <partDescription>Black Beach Bar Handlebar</partDescription>
    <unitOfMeasure>Each</unitOfMeasure>
    <brandName>LA CHOPPERS</brandName>
    <supplierNumber>LA-7312-01B</supplierNumber>
    <specialInstructions/>
    <baseDealerPrice>106.5000</baseDealerPrice>
    <yourDealerPrice>106.5000</yourDealerPrice>
    <baseRetailPrice>157.9500</baseRetailPrice>
    <originalRetailPrice>157.9500</originalRetailPrice>
    <partImage>http://asset.lemansnet.com/z/LzMvRS82LzNFNjlFOTdDLTg5NjEtNDU1MC1BRkY3LUExNjU0MTdEQUQ5MQ==</partImage>
    <productId>0635669078</productId>
    <productName>Hefty 1-1/4" Handlebar — Beach Bar/Hefty</productName>
  </part>
</root>

处理数据的当前 XSLT,除注释掉的部分外,其他所有内容都可以正常工作.

Current XSLT that processes the data, where everything else works except the commented out section.

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

    <xsl:template match="root">
        <xsl:element name="items">
            <xsl:for-each select="part">
                <xsl:if test="supplierNumber != '' and partStatusDescription != 'DISCONTINUED'     "> 
                    <xsl:element name="item">
                        <partNumber>
                            <xsl:value-of select="partNumber"/>
                        </partNumber>
                        <xsl:element name="name">
                             <xsl:value-of select="concat(brandName,' ',productName)"/>
                        </xsl:element>
                        <punctuatedPartNumber>
                            <xsl:value-of select="punctuatedPartNumber"/>
                        </punctuatedPartNumber>
                         <xsl:element name="is_in_stock">
                            <xsl:if test="partStatusDescription = 'STANDARD'">
                                    <xsl:value-of select="1"/>
                            </xsl:if>
                            <xsl:if test="partStatusDescription != 'STANDARD'">
                                <xsl:value-of select="0"/>
                            </xsl:if>    
                        </xsl:element>
                        <partDescription>
                            <xsl:value-of select="partDescription"/>
                        </partDescription>
                        <unitOfMeasure>
                            <xsl:value-of select="unitOfMeasure"/>
                        </unitOfMeasure>
                        <brandName>
                            <xsl:value-of select="brandName"/>
                        </brandName>
                        <supplierNumber>
                            <xsl:value-of select="supplierNumber"/>
                        </supplierNumber>
                        <specialInstructions>
                            <xsl:value-of select="specialInstructions"/>
                        </specialInstructions>
                        <xsl:element name="price">
                            <xsl:value-of select="(originalRetailPrice * 100) div 100"/>
                        </xsl:element>
                        <xsl:element name="special_price">
                            <xsl:if test="baseRetailPrice  &lt; originalRetailPrice">
                                <xsl:value-of select="baseRetailPrice"/>
                            </xsl:if>
                        </xsl:element>
                        <partImage>
                            <xsl:value-of select="partImage"/>
                        </partImage>
                        <productName>
                            <xsl:value-of select="productName"/>
                        </productName>
                        <productImage>
                            <xsl:value-of select="productImage"/>
                        </productImage>
                        <bullet1>
                            <xsl:value-of select="bullet1"/>
                        </bullet1>
                        <bullet2>
                            <xsl:value-of select="bullet2"/>
                        </bullet2>
                        <bullet3>
                            <xsl:value-of select="bullet3"/>
                        </bullet3>
                        <bullet4>
                            <xsl:value-of select="bullet4"/>
                        </bullet4>

                        <!-- finish -->
                        <xsl:choose>
                            <xsl:when test="contains(partDescription, 'Black')">
                                <finish>Black</finish>
                            </xsl:when>
                            <xsl:when test="contains(partDescription, 'Flat Back')">
                                <finish>Flat Back</finish>
                            </xsl:when>
                            <xsl:when test="contains(partDescription, 'Chrome')">
                                <finish>Chrome</finish>
                            </xsl:when>
                        </xsl:choose>
                        
                        <!-- size -->
                        <xsl:call-template name="find-size">
                            <xsl:with-param name="text" select="partDescription"/>
                        </xsl:call-template>
                       
                        <!-- I understand this wouldn't work as I'm just checking the total nodes, but I think someonehow I need to set the value of this node as a variable, and then check the count of this variable. This is easy in PHP, but I don't fully understand XSL  -->
                        <xsl:if test="count(/root/part/configurable_id) &gt; 1">
                            <xsl:element name="configurable_id">
                                <xsl:value-of select="productId"/>
                            </xsl:element>
                        </xsl:if>

                    </xsl:element>
                </xsl:if>
            </xsl:for-each>
        </xsl:element>
    </xsl:template>

    <xsl:template name="find-size">
        <xsl:param name="text"/>
        <xsl:param name="delimiter" select="' '"/>
        <xsl:variable name="token" select="substring-before(concat($text, $delimiter), $delimiter)" />
        <xsl:choose>
            <xsl:when test="starts-with(translate($token, '123456789', '000000000'), '0')">
                <size>
                    <xsl:value-of select="$token"/>
                </size>
            </xsl:when>
            <xsl:when test="contains($text, $delimiter)">
                <!-- recursive call -->
                <xsl:call-template name="find-size">
                    <xsl:with-param name="text" select="substring-after($text, $delimiter)"/>
                </xsl:call-template>
            </xsl:when>
        </xsl:choose>
    </xsl:template>

</xsl:stylesheet>

推荐答案

要检查 XSLT 1.0 中某个值的唯一性,您可以对 慕尼黑分组.

To check the uniqueness of a value in XSLT 1.0, you can use a slight modification of Muenchian grouping.

这是一个最小示例:

XSLT 1.0

<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:key name="part-by-product" match="part" use="productId" />

<xsl:template match="/root">
    <items>
        <xsl:for-each select="part[supplierNumber/text() and partStatusDescription != 'DISCONTINUED']">
            <item>
                <xsl:copy-of select="partNumber | productId"/>
                <!-- check productId uniqueness -->
                <xsl:if test="count(key('part-by-product', productId)) > 1">
                    <configurable_id>
                        <xsl:value-of select="productId"/>
                    </configurable_id>
                </xsl:if>
            </item>
        </xsl:for-each>
    </items>        
</xsl:template>

</xsl:stylesheet>

应用于您的输入示例,这将返回:

Applied to your input example, this will return:

结果

<?xml version="1.0" encoding="UTF-8"?>
<items>
  <item>
    <partNumber>06012660</partNumber>
    <productId>0243176820</productId>
    <configurable_id>0243176820</configurable_id>
  </item>
  <item>
    <partNumber>06012663</partNumber>
    <productId>0243176820</productId>
    <configurable_id>0243176820</configurable_id>
  </item>
  <item>
    <partNumber>06011482</partNumber>
    <productId>0635669078</productId>
  </item>
</items>


与您的问题无关:


Unrelated to your question:

注意使用谓词而不是xsl:if文字结果元素代替 xsl:element 以减少代码量.

Note the use of a predicate instead of xsl:if and literal result elements instead of xsl:element to reduce the amount of code.

这篇关于XSLT 1.0 - 使用 Vanilla XSLT 1.0 或 PHP XSLT 的节点中值唯一性的输出计数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆