首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >根据公共id元素的值合并两个xml文件xslt 3

根据公共id元素的值合并两个xml文件xslt 3
EN

Stack Overflow用户
提问于 2022-06-29 10:52:11
回答 1查看 71关注 0票数 2
代码语言:javascript
复制
<breakfast_menu>
<food>
<name>Belgian Waffles</name>
<id>$5</id>
<description>Two of our famous Belgian Waffles with plenty of real maple syrup</description>
<calories>650</calories>
</food>
<food>
<name>Strawberry Belgian Waffles</name>
<id>7</id>
<description>Light Belgian waffles covered with strawberries and whipped cream</description>
<calories>900</calories>
</food>
<food>
<name>Berry-Berry Belgian Waffles</name>
<id>8</id>
<description>Light Belgian waffles covered with an assortment of fresh berries and whipped cream</description>
<calories>900</calories>
</food>
<food>
<name>French Toast</name>
<id>4</id>
<description>Thick slices made from our homemade sourdough bread</description>
<calories>600</calories>
</food>
<food>
<name>Homestyle Breakfast</name>
<id>6</id>
<description>Two eggs, bacon or sausage, toast, and our ever-popular hash browns</description>
<calories>950</calories>
</food>
</breakfast_menu>

我试图在xsl:merge的帮助下完成这项任务。在我的试验中,我必须在xsl中具体定义要检索的元素。您如何建议在xslt-3的帮助下,从第二个xml文件中检索所有元素,减去已经存在于XML文件A中的id元素,并用作将两个xml文件合并为一个的匹配条件?

第二个xml文件:

代码语言:javascript
复制
<CATALOG>
<PLANT>
<COMMON>Butterfly Weed</COMMON>
<BOTANICAL>Asclepias tuberosa</BOTANICAL>
<ZONE>Annual</ZONE>
<LIGHT>Sunny</LIGHT>
<id>2</id>
<AVAILABILITY>063099</AVAILABILITY>
</PLANT>
<PLANT>
<COMMON>Primrose</COMMON>
<BOTANICAL>Oenothera</BOTANICAL>
<ZONE>3 - 5</ZONE>
<LIGHT>Sunny</LIGHT>
<id>6</id>
<AVAILABILITY>013099</AVAILABILITY>
</PLANT>
<PLANT>
<COMMON>Gentian</COMMON>
<BOTANICAL>Gentiana</BOTANICAL>
<ZONE>4</ZONE>
<LIGHT>Sun or Shade</LIGHT>
<id>17</id>
<AVAILABILITY>051899</AVAILABILITY>
</PLANT>
<PLANT>
<COMMON>Blue Gentian</COMMON>
<BOTANICAL>Gentiana</BOTANICAL>
<ZONE>4</ZONE>
<LIGHT>Sun or Shade</LIGHT>
<id>18</id>
<AVAILABILITY>050299</AVAILABILITY>
</PLANT>
<PLANT>
<COMMON>Jacob's Ladder</COMMON>
<BOTANICAL>Polemonium caeruleum</BOTANICAL>
<ZONE>Annual</ZONE>
<LIGHT>Shade</LIGHT>
<id>9</id>
<AVAILABILITY>022199</AVAILABILITY>
</PLANT>
<PLANT>
<COMMON>Greek Valerian</COMMON>
<BOTANICAL>Polemonium caeruleum</BOTANICAL>
<ZONE>Annual</ZONE>
<LIGHT>Shade</LIGHT>
<id>4</id>
<AVAILABILITY>071499</AVAILABILITY>
</PLANT>
<PLANT>
<COMMON>California Poppy</COMMON>
<BOTANICAL>Eschscholzia californica</BOTANICAL>
<ZONE>Annual</ZONE>
<LIGHT>Sun</LIGHT>
<id>7</id>
<AVAILABILITY>032799</AVAILABILITY>
</PLANT>
<PLANT>
<COMMON>Shooting Star</COMMON>
<BOTANICAL>Dodecatheon</BOTANICAL>
<ZONE>Annual</ZONE>
<LIGHT>Mostly Shady</LIGHT>
<id>8</id>
<AVAILABILITY>051399</AVAILABILITY>
</PLANT>
<PLANT>
<COMMON>Snakeroot</COMMON>
<BOTANICAL>Cimicifuga</BOTANICAL>
<ZONE>Annual</ZONE>
<LIGHT>Shade</LIGHT>
<id>5</id>
<AVAILABILITY>071199</AVAILABILITY>
</PLANT>
<PLANT>
<COMMON>Cardinal Flower</COMMON>
<BOTANICAL>Lobelia cardinalis</BOTANICAL>
<ZONE>2</ZONE>
<LIGHT>Shade</LIGHT>
<id>3</id>
<AVAILABILITY>022299</AVAILABILITY>
</PLANT>
</CATALOG>

期望产出:

代码语言:javascript
复制
<breakfast_menu>
<food>
<name>Belgian Waffles</name>
<id>5</id>
<description>Two of our famous Belgian Waffles with plenty of real maple syrup</description>
<calories>650</calories>
<COMMON>Snakeroot</COMMON>
<BOTANICAL>Cimicifuga</BOTANICAL>
<ZONE>Annual</ZONE>
<LIGHT>Shade</LIGHT>
<AVAILABILITY>071199</AVAILABILITY>
</food>
<food>
<name>Strawberry Belgian Waffles</name>
<id>7</id>
<description>Light Belgian waffles covered with strawberries and whipped cream</description>
<calories>900</calories>
<COMMON>California Poppy</COMMON>
<BOTANICAL>Eschscholzia californica</BOTANICAL>
<ZONE>Annual</ZONE>
<LIGHT>Sun</LIGHT>
<AVAILABILITY>032799</AVAILABILITY>
</food>
<food>
<name>Berry-Berry Belgian Waffles</name>
<id>8</id>
<description>Light Belgian waffles covered with an assortment of fresh berries and whipped cream</description>
<calories>900</calories>
<COMMON>Shooting Star</COMMON>
<BOTANICAL>Dodecatheon</BOTANICAL>
<ZONE>Annual</ZONE>
<LIGHT>Mostly Shady</LIGHT>
<AVAILABILITY>051399</AVAILABILITY>
</food>
<food>
<name>French Toast</name>
<id>4</id>
<description>Thick slices made from our homemade sourdough bread</description>
<calories>600</calories>
<COMMON>Greek Valerian</COMMON>
<BOTANICAL>Polemonium caeruleum</BOTANICAL>
<ZONE>Annual</ZONE>
<LIGHT>Shade</LIGHT>
<AVAILABILITY>071499</AVAILABILITY>
</food>
<food>
<name>Homestyle Breakfast</name>
<id>6</id>
<description>Two eggs, bacon or sausage, toast, and our ever-popular hash browns</description>
<calories>950</calories>
<COMMON>Primrose</COMMON>
<BOTANICAL>Oenothera</BOTANICAL>
<ZONE>3 - 5</ZONE>
<LIGHT>Sunny</LIGHT>
<AVAILABILITY>013099</AVAILABILITY>
</food>
</breakfast_menu>

我的方法之一是给你一个想法:

代码语言:javascript
复制
 <?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="#all"
    expand-text="yes"
    version="3.0">
    
  <xsl:param name="doc-A" select="doc('fileB.xml')"/>
  

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

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

  <xsl:template match="/*">
    <xsl:copy>
        <xsl:merge>
            <xsl:merge-source sort-before-merge="yes" for-each-item="." select="food">
                <xsl:merge-key select="id"/>
            </xsl:merge-source>
            <xsl:merge-source sort-before-merge="yes" for-each-item="$doc-A" select="//PLANT">
                <xsl:merge-key select="id"/>
            </xsl:merge-source>
            <xsl:merge-action>
  <xsl:copy>
   <xsl:copy-of select="current-merge-group('A')/*, current-merge-group('B')/(* except id)"/>
  </xsl:copy>
</xsl:merge-action>
        </xsl:merge>
    </xsl:copy>
  </xsl:template>
  
      <xsl:param name="merge-data"/>
      <xsl:copy>{.}{$merge-data}</xsl:copy>
  </xsl:template>
  
      <xsl:param name="merge-data"/>
      <xsl:next-match/>
  </xsl:template>
  
</xsl:stylesheet>
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-06-29 12:40:58

我会用。

代码语言:javascript
复制
<xsl:merge-action>
  <xsl:copy>
   <xsl:copy-of select="current-merge-group('A')/*, current-merge-group('B')/(* except id)"/>
  </xsl:copy>
</xsl:merge-action>

这显然是假设您正在命名您的合并源,这是您在代码中最初所做的,您在我的回答go图之后对其进行了编辑。

无论如何,您似乎也想忽略第二个文件中的数据,因此合并操作需要检查来自A的合并源:

代码语言:javascript
复制
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    version="3.0">

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

  <xsl:template match="/*">
    <xsl:copy>
        <xsl:merge>
            <xsl:merge-source name="A" sort-before-merge="yes" for-each-item="." select="food">
                <xsl:merge-key select="id"/>
            </xsl:merge-source>
            <xsl:merge-source name="B" sort-before-merge="yes" for-each-item="$doc-A" select="//PLANT">
                <xsl:merge-key select="id"/>
            </xsl:merge-source>
            <xsl:merge-action>
              <xsl:if test="current-merge-group('A')">
                 <xsl:copy>
                  <xsl:copy-of select="current-merge-group('A')/*, current-merge-group('B')/(* except id)"/>
                </xsl:copy>               
              </xsl:if>
            </xsl:merge-action>
      </xsl:merge>
    </xsl:copy>
  </xsl:template>
  
  <xsl:param name="doc-A" select="doc('fileB.xml')"/>

</xsl:stylesheet>

最后,考虑到xsl:merge需要订购输入源才能工作,而且您想要的输出似乎不是基于id排序的,我认为基于键的解决方案可能会更好地工作:

代码语言:javascript
复制
<xsl:param name="ref" match="PLANT" use="id"/>

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

代码语言:javascript
复制
<xsl:template match="food[key('ref', id, doc('fileB.xml'))]">
  <xsl:copy>
    <xsl:apply-templates select="*, key('ref', id, doc('fileB.xml'))/(* except id)"/>
  </xsl:copy>
</xsl:template>
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72800153

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档