在XSLT中选择具有条件的特定xml记录

时间:2014-02-14 10:11:37

标签: xslt-1.0

我有不同供应商名称的价格记录。我想按日期的价格购买供应商的最新价格。请帮助

<price_record>
<price>222.5</price>
<price_date>20060724</price_date>
<price_supplier_name>ABC ></price_supplier_name>
<seq_num>1</seq_num>
</price_record>

  <price_record>
  <price>382.5</price>
  <price_date>20080725</price_date>    
  <price_supplier_name>ABC  </price_supplier_name>
  <seq_num>2</seq_num>
  </price_record>

  <price_record>
  <price>88.58</price>
  <price_date>20060928</price_date>    
  <price_supplier_name>YZ ></price_supplier_name>
  <seq_num>3</seq_num>
  </price_rec

  <price_record>
  <price>78</price>
  <price_date>20060928</price_date>    
  <price_supplier_name>YZ ></price_supplier_name>
  <seq_num>3</seq_num>
  </price_record>

我想为每个供应商获得独特的价格(按最新日期)。

3 个答案:

答案 0 :(得分:0)

鉴于此XML输入

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <price_record>
        <price>222.5</price>
        <price_date>20060724</price_date>
        <price_supplier_name>ABC</price_supplier_name>
        <seq_num>1</seq_num>
    </price_record>

    <price_record>
        <price>382.5</price>
        <price_date>20080725</price_date>
        <price_supplier_name>ABC</price_supplier_name>
        <seq_num>2</seq_num>
    </price_record>

    <price_record>
        <price>88.58</price>
        <price_date>20060927</price_date>
        <price_supplier_name>YZ</price_supplier_name>
        <seq_num>3</seq_num>
    </price_record>

    <price_record>
        <price>78</price>
        <price_date>20060928</price_date><!-- modified  -->
        <price_supplier_name>YZ</price_supplier_name>
        <seq_num>3</seq_num>
    </price_record>
</root>

和这个样式表:

<?xml version="1.0" encoding="UTF-8"?>
<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:variable name="Suppliers">
        <xsl:for-each select="root/price_record/price_supplier_name">
            <xsl:value-of select="."/>
            <xsl:text>,</xsl:text>
        </xsl:for-each>
    </xsl:variable>

    <xsl:template match="root">
        <xsl:copy>
            <xsl:for-each select="price_record">
                <xsl:choose>
                    <xsl:when test="position()!=last()">
                        <xsl:choose>
                            <xsl:when test="following::price_record[price_date &gt; current()/price_date]/price_supplier_name = current()/price_supplier_name or preceding::price_record[price_date &gt; current()/price_date]/price_supplier_name = current()/price_supplier_name"/>

                            <xsl:otherwise>
                                <xsl:copy>
                                    <xsl:apply-templates/>
                                </xsl:copy>
                            </xsl:otherwise>
                        </xsl:choose>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:choose>
                            <xsl:when test="contains($Suppliers, current()/price_supplier_name) and preceding::price_record[price_date &gt; current()/price_date]/price_supplier_name = current()/price_supplier_name"/>
                            <xsl:otherwise>
                                <xsl:copy>
                                    <xsl:apply-templates/>
                                </xsl:copy>
                            </xsl:otherwise>
                        </xsl:choose>

                    </xsl:otherwise>
                </xsl:choose>
            </xsl:for-each>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

输出

<?xml version="1.0" encoding="utf-8"?>
<root>
    <price_record>
        <price>382.5</price>
        <price_date>20080725</price_date>
        <price_supplier_name>ABC</price_supplier_name>
        <seq_num>2</seq_num>
    </price_record>
    <price_record>
        <price>78</price>
        <price_date>20060928</price_date>
        <!-- modified  -->
        <price_supplier_name>YZ</price_supplier_name>
        <seq_num>3</seq_num>
    </price_record>
</root>

答案 1 :(得分:0)

您可以使用此XSLT:

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

<xsl:output indent="yes"/>


<xsl:template match ="price_records">
    <xsl:copy>
        <xsl:for-each-group select="price_record" group-by="price_supplier_name">
            <xsl:for-each select="current-group()">
                <xsl:sort select="price_date" order="descending"/>
                <xsl:if test="position() = 1">
                    <xsl:copy-of select="."/>
                </xsl:if>
            </xsl:for-each>
        </xsl:for-each-group>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

答案 2 :(得分:0)

我想我会继续发一个答案。以下XSLT代码使用XSL 1.0中的Muenchian分组来获得 a 唯一价格,这是每个供应商的最新价格。我几次读了你的问题,除非我错过了什么,你只要求最近的价格,但是当一个供应商在同一天出现两种不同的价格时,没有澄清你想要的东西......就是这种情况为“YZ”供应商。但是由于XML无论如何都不完整,我认为为了简单起见它是一个错字。你走了:

<?xml version="1.0" encoding="UTF-8"?>

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

<xsl:key name="supplierToRecord" match="price_record" use="price_supplier_name"/>
<xsl:template match="root">
    <root>
    <xsl:for-each select="price_record[generate-id()=generate-id(key('supplierToRecord', price_supplier_name)[1])]">
        <xsl:for-each select="key('supplierToRecord', price_supplier_name)">
            <xsl:sort select="price_date" order="descending"/>
            <xsl:if test="position() = 1">
                <xsl:copy-of select="."/>
            </xsl:if>
        </xsl:for-each>
    </xsl:for-each>
    </root>
</xsl:template>

</xsl:stylesheet>