【问题标题】:Merging data from multiple xml files without duplicates using XSLT使用 XSLT 合并来自多个 xml 文件的数据而不重复
【发布时间】:2016-05-20 18:46:19
【问题描述】:

有人提出了类似的问题,我已经阅读了这些问题,并尝试使用教程来解决这个问题,但没能做到。我确信这是编写正确的 xpath 的问题,但我似乎无法弄清楚。我正在尝试获取文件列表(基本上是文件夹中的所有内容)并将它们组合成不同的模式格式。诀窍是来自单个文件的部分信息需要用作生成的 XML 中的查找表。我的解决方案必须是纯 XSLT1.0。不用说,下面的一切都是虚构的……除了“清单” xml 文件的结构可能如下所示:

<files>
    <file>request1.xml</xml>
    <file>request2.xml</xml>
    <file>request3.xml</xml>
<files>

Request1.xml 文件可能如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<ProductList xmlns:pl="http://products.produsor.com/pml" xmlns:pi="http://standards.product.produsor.com/pml" createDateTime="2014-05-06T18:13:51.0Z" version="5.0">
    <pl:Request requestId="ADF87A9DF7" quantity="1">
        <pl:SystemIdentifier name="GUID">38DDF5C1-A049-44DB-9EEA-3F5CB831228D</pl:SystemIdentifier>
        <pl:SystemIdentifier name="UPC">4236483268</pl:SystemIdentifier>
        <pl:Product>
            <pl:Names>
                <pi.ProductNameLongDescription>Classic Design Round Dinning Table</pi.ProductNameLongDescription>
                <pi.ProductNameShort>Dinning Table</pi.ProductNameShort>
            </pl:Names>
            <pl:Description>
                <pi.ProductLongDescription>This is a really awesome table.</pi.ProductLongDescription>
                <pi.ProductShortDescription>It's made of wood</pi.ProductShortDescription>
            </pl:Description>
            <pl:Category>
                <pl:Name>Table</pl:Name>
                <pl:Description>This category is for tables</pl:Description>
                <pl:Priority>1</pl:Priority>
            </pl:Category>
            <pl:Category>
                <pl:Name>Dinning Furniture</pl:Name>
                <pl:Description>This category is for Dinning Furniture</pl:Description>
                <pl:Priority>2</pl:Priority>
            </pl:Category>
            <pl:Category>
                <pl:Name>Wood Furniture</pl:Name>
                <pl:Description>This category is for Wood Furniture</pl:Description>
                <pl:Priority>3</pl:Priority>
            </pl:Category>
        </pl:Product>
    </pl:Request>
    <pl:Request requestId="DA7FDAFDA9" quanitity="1">
        <pl:SystemIdentifier name="GUID">DA7FDAFD-B049-45DB-9FFA-3F5CB834328D</pl:SystemIdentifier>
        <pl:SystemIdentifier name="UPC">4236483269</pl:SystemIdentifier>
        <pl:Product>
            <pl:Names>
                <pi.ProductNameLongDescription>Classic Design Round Coffee Table</pi.ProductNameLongDescription>
                <pi.ProductNameShort>Coffee Table</pi.ProductNameShort>
            </pl:Names>
            <pl:Description>
                <pi.ProductLongDescription>This is a really awesome table.</pi.ProductLongDescription>
                <pi.ProductShortDescription>It is made of wood</pi.ProductShortDescription>
            </pl:Description>
            <pl:Category>
                <pl:Name>Table</pl:Name>
                <pl:Description>This category is for tables</pl:Description>
                <pl:Priority>1</pl:Priority>
            </pl:Category>
            <pl:Category>
                <pl:Name>Living Room Furniture</pl:Name>
                <pl:Description>This category is for Dinning Furniture</pl:Description>
                <pl:Priority>4</pl:Priority>
            </pl:Category>
            <pl:Category>
                <pl:Name>Wood Furniture</pl:Name>
                <pl:Description>This category is for Wood Furniture</pl:Description>
                <pl:Priority>3</pl:Priority>
            </pl:Category>
        </pl:Product>
    </pl:Request>
</ProductList>

Request2.xml 会是这样的:

<?xml version="1.0" encoding="UTF-8"?>
<ProductList xmlns:pl="http://products.produsor.com/pml" xmlns:pi="http://standards.product.produsor.com/pml" createDateTime="2014-05-06T18:13:51.0Z" version="5.0">
    <pl:Request requestId="DFADF08D0A" quantity="10">
        <pl:SystemIdentifier name="GUID">38DDF5C1-A049-44DB-9EEA-3F5CB831228D</pl:SystemIdentifier>
        <pl:SystemIdentifier name="UPC">4236483268</pl:SystemIdentifier>
        <pl:Product>
            <pl:Names>
                <pi.ProductNameLongDescription>Classic Design Round Dinning Table</pi.ProductNameLongDescription>
                <pi.ProductNameShort>Dinning Table</pi.ProductNameShort>
            </pl:Names>
            <pl:Description>
                <pi.ProductLongDescription>This is a really awesome table.</pi.ProductLongDescription>
                <pi.ProductShortDescription>It's made of wood</pi.ProductShortDescription>
            </pl:Description>
            <pl:Category>
                <pl:Name>Table</pl:Name>
                <pl:Description>This category is for tables</pl:Description>
                <pl:Priority>1</pl:Priority>
            </pl:Category>
            <pl:Category>
                <pl:Name>Dinning Furniture</pl:Name>
                <pl:Description>This category is for Dinning Furniture</pl:Description>
                <pl:Priority>2</pl:Priority>
            </pl:Category>
            <pl:Category>
                <pl:Name>Wood Furniture</pl:Name>
                <pl:Description>This category is for Wood Furniture</pl:Description>
                <pl:Priority>3</pl:Priority>
            </pl:Category>
        </pl:Product>
    </pl:Request>
    <pl:Request requestId="RER7689EQ9" quanitity="10">
        <pl:SystemIdentifier name="GUID">DA7FDAFD-B049-45DB-9FFA-3F5CB834328D</pl:SystemIdentifier>
        <pl:SystemIdentifier name="UPC">4236483269</pl:SystemIdentifier>
        <pl:Product>
            <pl:Names>
                <pi.ProductNameLongDescription>Classic Design Round Coffee Table</pi.ProductNameLongDescription>
                <pi.ProductNameShort>Coffee Table</pi.ProductNameShort>
            </pl:Names>
            <pl:Description>
                <pi.ProductLongDescription>This is a really awesome table.</pi.ProductLongDescription>
                <pi.ProductShortDescription>It is made of wood</pi.ProductShortDescription>
            </pl:Description>
            <pl:Category>
                <pl:Name>Table</pl:Name>
                <pl:Description>This category is for tables</pl:Description>
                <pl:Priority>1</pl:Priority>
            </pl:Category>
            <pl:Category>
                <pl:Name>Living Room Furniture</pl:Name>
                <pl:Description>This category is for Dinning Furniture</pl:Description>
                <pl:Priority>4</pl:Priority>
            </pl:Category>
            <pl:Category>
                <pl:Name>Wood Furniture</pl:Name>
                <pl:Description>This category is for Wood Furniture</pl:Description>
                <pl:Priority>3</pl:Priority>
            </pl:Category>
        </pl:Product>
    </pl:Request>
</ProductList>

我想要的是以下内容:

<ProductList xmlns:pl="http://products.produsor.com/pml">
    <pl:Submission>
<!--********* This is the problem area *************-->
        <pl:Descriptions>
            <pl:Description id="1">This is a really awesome table.</pl:Description>
        </pl:Descriptions>
        <pl:Categories>
            <pl:Category id="1">Table</pl:Category>
            <pl:Category id="2">Dinning Furniture</pl:Category>
            <pl:Category id="3">Living Room Furniture</pl:Category>
            <pl:Category id="4">Wood Furniture</pl:Category>
        </pl:Categories>
<!--****************************************************-->
        <pl:Product>
            <pl:SystemIdentifier type="GUID">DA7FDAFD-B049-45DB-9FFA-3F5CB834328D</pl:SystemIdentifier>
            <pl:SystemIdentifier name="UPC">4236483268</pl:SystemIdentifier>
            <pl:ProductName descriptionId="1">Dinning Table</pl:ProductName>
            <cat catId="1"/>
            <cat catId="2"/>
            <cat catId="3"/>
        </pl:Product>
        <pl:Product>
            <pl:SystemIdentifier type="GUID">DA7FDAFD-B049-45DB-9FFA-3F5CB834328D</pl:SystemIdentifier>
            <pl:SystemIdentifier name="UPC">4236483268</pl:SystemIdentifier>
            <pl:ProductName descriptionId="1">Dinning Table</pl:ProductName>
            <cat catId="1"/>
            <cat catId="3"/>
            <cat catId="4"/>
        </pl:Product>       
        <pl:Product>
            <pl:SystemIdentifier type="GUID">DA7FDAFD-B049-45DB-9FFA-3F5CB834328D</pl:SystemIdentifier>
            <pl:SystemIdentifier name="UPC">4236483268</pl:SystemIdentifier>
            <pl:ProductName descriptionId="1">Dinning Table</pl:ProductName>
            <cat catId="1"/>
            <cat catId="2"/>
            <cat catId="3"/>
        </pl:Product>
        <pl:Product>
            <pl:SystemIdentifier type="GUID">DA7FDAFD-B049-45DB-9FFA-3F5CB834328D</pl:SystemIdentifier>
            <pl:SystemIdentifier name="UPC">4236483268</pl:SystemIdentifier>
            <pl:ProductName descriptionId="1">Dinning Table</pl:ProductName>
            <cat catId="1"/>
            <cat catId="3"/>
            <cat catId="4"/>
        </pl:Product>   
    </pl:Submission>
</ProductList>

诀窍是我不能在pl:Descriptionpl:category 标记中包含重复值。如果产品元素在文件中重复,则要求它们重复。我已经构建了 xslt 模板来构建所有内容,包括描述和类别,但它对每个文件都执行此操作。我需要它构建描述和类别,包括来自所有文件的不同数据,然后是所有产品元素。这是我目前所拥有的,它构建了产品元素。

<xsl:template match="/">
    <xsl:for-each select="/files/file">
        <xsl:apply-templates select="document(.)/ProductList/pl:Request"/>
    </xsl:for-each>
</xsl:template>

由于这已经很长了,我只想说请求模板用于创建产品元素,我有一个“ProductList”模板,它将创建描述和类别元素结构。

【问题讨论】:

  • 如果您需要合并多个文件,请向我们展示两个最小样本和合并结果,并说明您要合并的标准。
  • 我已编辑以包含文件的另一个示例(它们几乎相同),这代表了数据在实际 xml 文件中的方式。我正在合并所有文件和数据。没有过滤“产品”的标准。
  • 你能用exsl:node-set或类似的吗?还是超越“纯”XSLT 1.0?
  • 还有结果中的&lt;pl:Category id="1"&gt;Table&lt;/pl:Category&gt; 元素,它们只是输入文档中所有pl:Category 的列表,还是您需要根据值消除重复项(例如Table)?
  • 结果中的 pl:Category 元素需要不同。除非我弄错了,否则您似乎已经在您发布的答案中考虑了这一点。谢谢。

标签: xml xslt xpath xslt-1.0


【解决方案1】:

这是一个将所有类别复制到结果树片段中的示例,使用 exsl:node-set 和 Muenchian 分组来标识唯一类别,然后在复制请求元素时引用它们:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:exsl="http://exslt.org/common"
    xmlns:pl="http://products.produsor.com/pml"
    version="1.0"
    exclude-result-prefixes="exsl">

    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:variable name="input-docs" select="document(files/file)"/>

    <xsl:variable name="cats-rtf">
        <xsl:copy-of select="$input-docs//pl:Category"/>
    </xsl:variable>

    <xsl:key name="group" match="pl:Category" use="pl:Name"/>

    <xsl:variable name="distinct-cats-rtf">
        <xsl:for-each select="exsl:node-set($cats-rtf)/pl:Category[generate-id() = generate-id(key('group', pl:Name)[1])]">
            <pl:Category id="{position()}">
                <xsl:value-of select="pl:Name"/>
            </pl:Category>
        </xsl:for-each>
    </xsl:variable>

    <xsl:variable name="distinct-cats" select="exsl:node-set($distinct-cats-rtf)/pl:Category"/>

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

    <xsl:template match="/">
        <ProductList>
            <pl:Submission>
                <pl:Categories>
                    <xsl:copy-of select="$distinct-cats"/>
                </pl:Categories>
                <xsl:apply-templates select="$input-docs//pl:Request"/>
            </pl:Submission>
        </ProductList>
    </xsl:template>

    <xsl:template match="pl:Category">
        <cat catId="{$distinct-cats[. = current()/pl:Name]/@id}"/>
    </xsl:template>

</xsl:stylesheet>

您可以使用相同的方法来识别独特的描述并引用它们。

【讨论】:

  • 谢谢。这看起来相当简单。我会尽快试一试(没有幸能够在家中完成这个项目)。
  • 不幸的是我不能使用 exsl。我尝试并得到“命名空间'exslt.org/common'不包含任何功能。”我猜这与我们的网络安全有关。
  • 好吧,找出您使用的 XSLT 处理器,例如通过您的处理器运行 home.arcor.de/martin.honnen/xslt/processorTest2.xml,然后查看其文档以了解将结果树片段转换为节点集的扩展函数。
  • @Mark_Eng,您知道您使用的是哪种 XSLT 处理器吗?不是所有的都支持exsl:node-set 扩展函数,最著名的是微软的 MSXML 和 XslTransform,但通常在自定义命名空间中支持专有扩展函数来完成相同的工作。
  • 我无法使用您的网站。它被我们的网络安全阻止(非常严格)。我一直在使用您上面的一些建议来制定一种方法来做我需要的事情。我还没有完全明白,但我想我可以用你上面给我的东西来做。我会继续并将其标记为已回答。谢谢。
猜你喜欢
  • 2019-01-29
  • 2013-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-24
相关资源
最近更新 更多