比较两个XML文件中的价格

时间:2015-10-24 13:39:14

标签: xml xslt

我不知道在两个XML文件中比较价格变化的最佳方法是什么。

使用XSLT,我从价目表中生成两个(一个实际的,一个较旧的)XML:

newer.xml:

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

older.xml

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

我尝试与diff工具进行并排比较,但在第二个XML中有许多新产品,所以它是不可能的。

使用XSLT生成新的XML可能会很好,但这超出了我的知识范围。

  • 产品由<code>
  • 标识
  • 检查产品价格是否更改,如果是复制元素(仅在此情况下)
  • 请勿检查或复制新产品(<code>中不存在older.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>

2 个答案:

答案 0 :(得分:1)

older.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

<?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

<?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>

现在在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>

答案 1 :(得分:1)

处理交叉引用的简单有效方法是使用XSLT内置的 key 机制:

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>

在XSLT 1.0中跨文档应用密钥有点复杂,但仍有可能。