【问题标题】:need to merge data from two xml files based on record id需要根据记录id合并两个xml文件中的数据
【发布时间】:2019-07-25 13:56:14
【问题描述】:

我有以下两个 xml 文件。 文件 A:

<breakfast_menu>
    <food>
        <id>1</id>
        <name>Belgian Waffles</name>
        <price>$5.95</price>
        <calories>650</calories>
    </food>
    <food>
        <id>2</id>
        <name>Strawberry Belgian Waffles</name>
        <price>$7.95</price>
        <calories>900</calories>
    </food>
</breakfast_menu>

和文件 B:

<breakfast_menu>
    <food>
        <id>1</id>
        <description>here we have already a description element</description>
        <otherData>s3650</otherData>
    </food>
    <food>
        <id>2</id>
        <otherData>s3250</otherData>
        <otherData2>g508</otherData2>
        <otherData3>sidi6098</otherData3>
    </food>
</breakfast_menu>

我无法实现的是,对于基于记录 id 匹配的每条记录,从名为 A 的 xml 文件中获取所有信息,并将所有这些信息放在文件 B 的描述元素中,但也要保留它来的元素从。如果匹配的记录没有描述元素,我们添加一个。如果它已经有一个,那么我们必须知道从文件 A 中获取的信息从哪里开始,带有一个文本分隔符,即“-followingInfoTakenFromFileA-”。因此,考虑到上述情况,所需的输出应该是:

 <breakfast_menu>
    <food>
        <id>1</id>
        <description>here we have already a description element-followingInfoTakenFromFileA-name:Belgian Waffles-price:$5.95-calories:650</description>
        <otherData>s3650</otherData>
    </food>
    <food>
        <id>2</id>
        <otherData>s3250</otherData>
        <otherData2>g508</otherData2>
        <otherData3>sidi6098</otherData3>
        <description>name:Strawberry Belgian Waffles-price:$7.95-calories:900</description>
    </food>
</breakfast_menu>

【问题讨论】:

  • 好吧,既然您已将问题标记为xslt-3.0 并在您的问题中使用了“合并”一词,那么您是否研究过XSLT 3 的特性,例如合并w3.org/TR/xslt-30/#merging?看起来您应该能够为您的样本提出一些方法,至少可以准确地向我们展示您遇到的问题。
  • 是的,我尝试过使用 xsl:merge,并且我有一个输出,其中包含许多描述元素。我只需要一个,使用上面显示的输出中描述的分隔符,我使用 saxon java 9.9 HE。我的努力类似于此处显示的示例:w3.org/TR/xslt-30/#merging
  • 请编辑您的问题并向我们展示您的 XSLT 代码及其给出的结果。
  • 我现在的代码不起作用,因此我根本无法得到任何结果,有点搞砸了:(

标签: xslt-3.0


【解决方案1】:

看来,给定已排序的 id 合并键,xsl:merge 的一项简单任务:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    expand-text="yes"
    version="3.0">

  <xsl:param name="doc-A">
<breakfast_menu>
    <food>
        <id>1</id>
        <name>Belgian Waffles</name>
        <price>$5.95</price>
        <calories>650</calories>
    </food>
    <food>
        <id>2</id>
        <name>Strawberry Belgian Waffles</name>
        <price>$7.95</price>
        <calories>900</calories>
    </food>
</breakfast_menu>
  </xsl:param>

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/*">
    <xsl:copy>
        <xsl:merge>
            <xsl:merge-source for-each-item="." select="food">
                <xsl:merge-key select="id"/>
            </xsl:merge-source>
            <xsl:merge-source for-each-item="$doc-A" select="//food">
                <xsl:merge-key select="id"/>
            </xsl:merge-source>
            <xsl:merge-action>
                <xsl:copy>
                    <xsl:apply-templates select="*">
                        <xsl:with-param name="merge-data" 
                          select="let $data := string-join(current-merge-group()[2]/(* except id)!(name() || ':' || .), '-')
                                  return if (description)
                                         then '-followingInfoTakenFrom' || document-uri(root(current-merge-group()[2])) || $data
                                         else $data"/>
                    </xsl:apply-templates>
                </xsl:copy>
            </xsl:merge-action>
        </xsl:merge>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="food/description">
      <xsl:param name="merge-data"/>
      <xsl:copy>{.}{$merge-data}</xsl:copy>
  </xsl:template>

  <xsl:template match="food[not(description)]/*[last()]">
      <xsl:param name="merge-data"/>
      <xsl:next-match/>
      <description>{$merge-data}</description>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/pPzifqo

该示例将第一个文档内嵌为示例的自包含参数,但在现实世界中,您可以使用例如从 URL 加载&lt;xsl:param name="doc-A" select="doc('fileA.xml')"/&gt;.

【讨论】:

  • 只是为了答案的完整性,如果一个人有一个未排序的 id 合并键,应该如何更改上述内容?这是一个较新的示例:xsltfiddle.liberty-development.net/pPzifqq 或者这应该是一个新问题?
  • @raka,请提出一个新问题,其中包含 XML 输入、所需输出、您拥有的代码、输出或您得到的错误的必要细节,除非您在 xsl:merge-sources 上使用 sort-before-merge="yes"已经解决了问题。
  • 这似乎可以完成这项工作。如果我在输出中看到奇怪的东西,我会告诉你,谢谢
猜你喜欢
  • 2021-08-17
  • 2014-03-31
  • 2015-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-29
相关资源
最近更新 更多