简体   繁体   English

比较两个XML文件中的价格

[英]Compare price in two XML files

I don't know what would be the best way to compare price changes in two XML files. 我不知道在两个XML文件中比较价格变化的最佳方法是什么。

With XSLT I generate two (one actual, one older) XML from a price list: 使用XSLT,我可以从价目表中生成两个(一个实际的,一个更旧的)XML:

newer.xml: newer.xml:

<xml>
  <produkt>
    <code>000161</code>
    <name>Test name</name>
    <available>Yes</available>
    <price>19,90</price>
  </produkt>
</xml>

older.xml old.xml

<xml>
  <produkt>
    <code>000161</code>
    <name>Test name</name>
    <available>Yes</available>
    <price>18,90</price>
  </produkt>
</xml>

I tried to do a side by side comparison with a diff tool, but in the second XML are many new products so it's impossible. 我试图与diff工具进行并排比较,但是在第二个XML中有许多新产品,所以这是不可能的。

Perhaps it would be good to generate a new XML with XSLT, but it's beyond my knowledge. 用XSLT生成新的XML也许会很好,但是这超出了我的知识。

  • products are identified by <code> 产品由<code>标识
  • check if product price changed, if yes copy element (and only in this case) 检查产品价格是否更改,如果是,则复制元素(仅在这种情况下)
  • don't check or copy new products ( <code> does not exist in older.xml : do not copy) 不要检查或复制新产品( <code>older.xml中不存在:请勿复制)

compare.xml compare.xml

<xml>
  <produkt>
    <code>000161</code>
    <name>Test name</name>
    <available>Yes</available>
    <oldprice>18,90</oldprice>
    <newprice>19,90</newprice>
  </produkt>
</xml>

older.xml old.xml

<?xml version="1.0" encoding="UTF-8"?>
<xml>
    <produkt>
        <code>000160</code>
        <name>Product A (only in old list)</name>
        <available>Yes</available>
        <price>9,90</price>
    </produkt>
    <produkt>
        <code>000161</code>
        <name>Product B (price falls)</name>
        <available>Yes</available>
        <price>19,90</price>
    </produkt>
    <produkt>
        <code>000163</code>
        <name>Product D (price rises)</name>
        <available>Yes</available>
        <price>24,90</price>
    </produkt>
    <produkt>
        <code>000164</code>
        <name>Product E (price unchanged)</name>
        <available>Yes</available>
        <price>99,90</price>
    </produkt>
</xml>

newer.xml newer.xml

<?xml version="1.0" encoding="UTF-8"?>
<xml>
    <produkt>
        <code>000161</code>
        <name>Product B (price falls)</name>
        <available>Yes</available>
        <price>18,90</price>
    </produkt>
    <produkt>
        <code>000162</code>
        <name>Product C (only in new list)</name>
        <available>Yes</available>
        <price>16,90</price>
    </produkt>
    <produkt>
        <code>000163</code>
        <name>Product D (price rises)</name>
        <available>Yes</available>
        <price>28,90</price>
    </produkt>
    <produkt>
        <code>000164</code>
        <name>Product E (price unchanged)</name>
        <available>Yes</available>
        <price>99,90</price>
    </produkt>
</xml>

compare.xsl compare.xsl

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">

    <xsl:output indent="yes"/>

    <xsl:template match="xml">
        <xsl:variable name="older" select="document('older.xml')"/>
        <xml>
            <xsl:for-each select="produkt">
                <xsl:variable name="code" select="code"/>
                <xsl:variable name="findProduktByCode" select="$older/xml/produkt[code = $code]"/>
                <xsl:if test="price != $findProduktByCode/price">
                    <produkt>
                        <xsl:copy-of select="code"/>
                        <xsl:copy-of select="name"/>
                        <xsl:copy-of select="available"/>
                        <oldprice>
                            <xsl:value-of select="$findProduktByCode/price"/>
                        </oldprice>
                        <newprice>
                            <xsl:value-of select="price"/>
                        </newprice>
                    </produkt>
                </xsl:if>
            </xsl:for-each>
        </xml>
    </xsl:template>

</xsl:stylesheet>

Now apply compare.xslt on newer.xml: 现在在newer.xml上应用compare.xslt:

<?xml version="1.0" encoding="UTF-8"?>
<xml>
   <produkt>
      <code>000161</code>
      <name>Product B (price falls)</name>
      <available>Yes</available>
      <oldprice>19,90</oldprice>
      <newprice>18,90</newprice>
   </produkt>
   <produkt>
      <code>000163</code>
      <name>Product D (price rises)</name>
      <available>Yes</available>
      <oldprice>24,90</oldprice>
      <newprice>28,90</newprice>
   </produkt>
</xml>

The easy and efficient way to handle cross-references is to use XSLT's built-in key mechanism: 处理交叉引用的一种简单有效的方法是使用XSLT的内置密钥机制:

XSLT 2.0 XSLT 2.0

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

<xsl:param name="path-to-old" select="'older.xml'"/>

<xsl:key name="product-by-code" match="produkt" use="code" />

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

<xsl:template match="produkt">
    <xsl:variable name="old-price" select="key('product-by-code', code, document($path-to-old))/price" />
    <xsl:if test="$old-price != price">
        <xsl:copy>
            <xsl:apply-templates select="@*|node() except price"/>
            <oldprice>
                <xsl:value-of select="$old-price"/>
            </oldprice>
            <newprice>
                <xsl:value-of select="price" />
            </newprice>
        </xsl:copy>
    </xsl:if>
</xsl:template>

</xsl:stylesheet>

Applying a key across documents is a bit more complicated in XSLT 1.0, but still possible. 在XSLT 1.0中,跨文档应用密钥比较复杂,但仍然可以实现。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM