基于条件合并XML文件的XSLT

基于条件合并XML文件的XSLT,xslt,xslt-1.0,mule-studio,Xslt,Xslt 1.0,Mule Studio,是否可以使用XSLT1.0合并两个xml数据文件-xml-01和xml-02。要使用的合并键应基于Xml-01中与Xml-02中的SystemName映射的值System 最终的输出应该和下面给出的一样(在文章的底部) 我正试图在Mule Studio的组件中实现这一点。它没有必要的特性,所以我尝试使用XSLT1.0 Xml-01 ID0012 系统007 ID0010 系统003 ID009 系统006 Xml-02 产品代码01 系统007 产品代码02 系统007 产品代码03 系统

是否可以使用XSLT1.0合并两个xml数据文件-
xml-01
xml-02
。要使用的合并键应基于
Xml-01
中与
Xml-02中的
SystemName
映射的值
System

最终的输出应该和下面给出的一样(在文章的底部)

我正试图在Mule Studio的组件中实现这一点。它没有必要的特性,所以我尝试使用XSLT1.0

Xml-01

ID0012
系统007
ID0010
系统003
ID009
系统006
Xml-02

产品代码01
系统007
产品代码02
系统007
产品代码03
系统003
最终产量-

ID0012
系统007
产品代码01
产品代码02
ID0010
系统003
产品代码03
ID009
系统006
代码在这里

这里的总体思路是Xml-01将是XSLT的主要输入文档,您将使用加载辅助Xml-02。

这可能是一个相当简单的查找,除了:

  • 在XSLT1.0中,使用键在文档间进行查找是很尴尬的
  • 您的查找文档使用了不同的名称空间(尽管 相同前缀)
  • 当查找失败时,需要添加空节点(真的有必要吗?)
  • 考虑到这一点,请尝试:

    XSLT1.0

    <xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:ns0="http://xmlns.jupiter.com/RetrieveMI"
    xmlns:ns1="http://xmlns.jupiter.com/RetrieveProducts"
    exclude-result-prefixes="ns1">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:strip-space elements="*"/>
    
    <xsl:param name="path-to-lookup" select="'02.xml'"/>
    
    <xsl:key name="product-by-system" match="ns1:Products" use="ns1:SystemName" />
    
    <!-- identity transform -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="ns0:ProductsList">
        <xsl:variable name="system" select="../ns0:System" />
        <xsl:copy>
            <!-- switch context to lookup document in order to use key -->
            <xsl:for-each select="document($path-to-lookup)">
                <xsl:variable name="matching-products" select="key('product-by-system', $system)" />
                <xsl:for-each select="$matching-products">
                    <ns0:ProductIDs>
                        <ns0:ProductID>
                            <xsl:value-of select="ns1:ProductCode"/>
                        </ns0:ProductID>
                    </ns0:ProductIDs>
                </xsl:for-each>
                <!-- add empty node when there is no match -->
                <xsl:if test="not($matching-products)">
                    <ns0:ProductIDs>
                        <ns0:ProductID/>
                    </ns0:ProductIDs>
                </xsl:if>
            </xsl:for-each>
        </xsl:copy>
    </xsl:template>
    
    </xsl:stylesheet>
    
    
    
    您不能使用用于创建文档节点的
    xsl:document
    加载文档。也许你指的是
    fn:doc
    fn:document
    ?你说得对,我的错——我指的是document()函数。我会修正我的答案。这是家庭作业吗?如果是的话,请说“是”,并展示你迄今为止所做的工作。如果没有,仍然显示您到目前为止所做的…;)。欢迎来到SO,请花一分钟阅读。请指定是使用XSLT 1.0还是2.0。我是XSLT新手,我尝试使用Mule Data mapper聚合负载,但这种方法不成功。@Vinu,我已更新了您的问题,以反映我认为您的意图,并链接到您提到的产品。不过,我想知道,如果您决定不使用给定的工具而选择另一个工具(XSLT),为什么不使用更新的版本呢?XSLT1.0已有17年历史,XSLT2.0从2007年开始,XSLT3.0即将推出。考虑使用或(同时支持大多数XSLT 3,免责声明,我共同写Exselt)。
    <ns0:ProductsResponse xmlns:ns0="http://xmlns.jupiter.com/RetrieveProducts">
      <ns0:Products>
        <ns0:ProductCode>ProductCode01</ns0:ProductCode>
        <ns0:SystemName>System007</ns0:SystemName>
      </ns0:Products>
      <ns0:Products>
        <ns0:ProductCode>ProductCode02</ns0:ProductCode>
        <ns0:SystemName>System007</ns0:SystemName>
      </ns0:Products>
      <ns0:Products>
        <ns0:ProductCode>ProductCode03</ns0:ProductCode>
        <ns0:SystemName>System003</ns0:SystemName>
      </ns0:Products>
      </ns0:ProductsResponse>
    
     <?xml version="1.0" encoding="UTF-8"?>
    <ns0:RetrieveMIProcessResponse xmlns:ns0="http://xmlns.jupiter.com/RetrieveMI">
      <ns0:Inquiry>
        <ns0:MIId>ID0012</ns0:MIId>
        <ns0:System>System007</ns0:System>
        <ns0:ProductsList>
          <ns0:ProductIDs>
            <ns0:ProductID>ProductCode01</ns0:ProductID>
          </ns0:ProductIDs>
           <ns0:ProductIDs>
            <ns0:ProductID>ProductCode02</ns0:ProductID>
          </ns0:ProductIDs>
        </ns0:ProductsList>
      </ns0:Inquiry>
      <ns0:Inquiry>
        <ns0:MIId>ID0010</ns0:MIId>
        <ns0:System>System003</ns0:System>
        <ns0:ProductsList>
          <ns0:ProductIDs>
            <ns0:ProductID>ProductCode03</ns0:ProductID>
          </ns0:ProductIDs>
        </ns0:ProductsList>
      </ns0:Inquiry>
      <ns0:Inquiry>
        <ns0:MIId>ID009</ns0:MIId>
        <ns0:System>System006</ns0:System>
        <ns0:ProductsList>
          <ns0:ProductIDs>
            <ns0:ProductID/>
          </ns0:ProductIDs>
        </ns0:ProductsList>
      </ns0:Inquiry>
     </ns0:RetrieveMIProcessResponse>
    
     code here
    
    <xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:ns0="http://xmlns.jupiter.com/RetrieveMI"
    xmlns:ns1="http://xmlns.jupiter.com/RetrieveProducts"
    exclude-result-prefixes="ns1">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:strip-space elements="*"/>
    
    <xsl:param name="path-to-lookup" select="'02.xml'"/>
    
    <xsl:key name="product-by-system" match="ns1:Products" use="ns1:SystemName" />
    
    <!-- identity transform -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="ns0:ProductsList">
        <xsl:variable name="system" select="../ns0:System" />
        <xsl:copy>
            <!-- switch context to lookup document in order to use key -->
            <xsl:for-each select="document($path-to-lookup)">
                <xsl:variable name="matching-products" select="key('product-by-system', $system)" />
                <xsl:for-each select="$matching-products">
                    <ns0:ProductIDs>
                        <ns0:ProductID>
                            <xsl:value-of select="ns1:ProductCode"/>
                        </ns0:ProductID>
                    </ns0:ProductIDs>
                </xsl:for-each>
                <!-- add empty node when there is no match -->
                <xsl:if test="not($matching-products)">
                    <ns0:ProductIDs>
                        <ns0:ProductID/>
                    </ns0:ProductIDs>
                </xsl:if>
            </xsl:for-each>
        </xsl:copy>
    </xsl:template>
    
    </xsl:stylesheet>