如何使用 xslt 连接两个或多个 xml 文件并保持顺序? [英] How to concatenate two or more xml files using xslt and maintain the order?

查看:24
本文介绍了如何使用 xslt 连接两个或多个 xml 文件并保持顺序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我有这个文件:输入file1.xml:

<schema>
    <sequence> 
        <nodeA id="a">
            <fruit id="small">
                <orange id="x" method="create">                    
                    <attributes>
                        <color>Orange</color>
                        <year>2000</year>
                    </attributes>
                </orange>                           
            </fruit>
            <fruit id="small">
                <apple id="x" method="create">                    
                    <attributes>
                        <color>Orange</color>
                        <year>2000</year>
                    </attributes>
                </apple>                           
            </fruit>
            <fruit id="medium">
                <orange id="x" method="create">                    
                    <attributes>
                        <color>Orange</color>
                        <year>2000</year>
                    </attributes>
                </orange>                           
            </fruit>
        </nodeA>
        <nodeB id="b">
            <dog id="large">
                <doberman id="x" method="create">
                    <condition>
                        <color>Black</color>
                    </condition>
                </doberman>
            </dog>
        </nodeB>
    </sequence>
</schema>

file2.xml:

<schema>
    <sequence>
        <nodeA id="a">
            <fruit id="small">
                <melon id="x" method="create">
                    <attributes>
                        <color>Orange</color>
                        <year>2000</year>
                    </attributes>
                </melon>
            </fruit>
        </nodeA>
        <nodeB id="b">
            <dog id="small">
                <poodle id="x" method="create">                    
                    <condition>
                        <color>White</color>
                    </condition>
                </poodle>  
            </dog>                
        </nodeB>
    </sequence>
</schema>

连接后:输出:concate.xml

<schema>
    <sequence>
        <nodeA id="a">
            <fruit id="small">
                <orange id="x" method="create">                    
                    <attributes>
                        <color>Orange</color>
                        <year>2000</year>
                    </attributes>
                </orange>                        
            </fruit>
            <fruit id="small">
                <apple id="x" method="create">                    
                    <attributes>
                        <color>Orange</color>
                        <year>2000</year>
                    </attributes>
                </apple>                           
            </fruit>
            <fruit id="medium">
                <orange id="x" method="create">                    
                    <attributes>
                        <color>Orange</color>
                        <year>2000</year>
                    </attributes>
                </orange>                           
            </fruit>
            <fruit id="small">
                <melon id="x" method="create">
                    <attributes>
                        <color>Orange</color>
                        <year>2000</year>
                    </attributes>
                </melon>
            </fruit>
        </nodeA>
        <nodeB id="b">
            <dog id="large">
                <doberman id="x" method="create">
                    <condition>
                        <color>Black</color>
                    </condition>
                </doberman>
            </dog>
            <dog id="small">
                <poodle id="x" method="create">                    
                    <condition>
                        <color>White</color>
                    </condition>
                </poodle>  
            </dog>                
        </nodeB>
    </sequence>
</schema>

对于连接,它将取决于文件顺序,因此 file2.xml 中的节点将放置在 file1.xml 节点下(如示例所示).我最多有 5 个文件.如何仅使用 xsl 转换来实现这一点,即 xslt 将同时输入 5 个文件并输出 1 个文件?

For the concate it will depend on the file order so the node in file2.xml will be placed under the node of file1.xml (as seen on the example). And I have up to 5 files. How is this achievable using xsl transformation only, i.e the xslt will input 5 files at the same time and outputting 1 file?

这是文档结构和我们合并的点:

<schema>
    <sequence> 
        <nodeA id="a">
            <fruit id="small">
                <orange id="x" method="create">                    
                    ...
                </orange>                
            </fruit>
            <fruit id="small">
                ...                          
            </fruit>
            <fruit id="large"> 
                ...                          
            </fruit>

            <!-- we merge below this -->
        </nodeA>

        <nodeB id="b">
            <dog id="large">
                <doberman id="x" method="create">
                    ...
                </doberman>
            </dog>
            <dog id="small">
                <doberman id="x" method="create">
                    ...
                </doberman>
            </dog>
        <!-- we merge below this -->
        </nodeB>

        <somenode id="any">
            ...    
        </somenode>
    </sequence>
</schema>

注意:如果不可能,只连接两个文件输入就可以了,因为它总是可以为其他文件重复.文件中还有各种节点名(nodeA、nodeB、SomeNode等),所以需要一些可以概括这个问题的东西.

Note: If not possible concatenating only two files input will be fine as it can always be repeated for the other files. Also there are various node name in the file (nodeA, nodeB, SomeNode, etc.)so something that can generalize this problem is needed.

我们可以使用 xsl1.0 或 2.0.

we can use xsl1.0 or 2.0.

非常感谢.约翰

推荐答案

@John,这是一个更通用的解决方案:

@John, here's a more generic solution:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:a="http://a.com">
   <xsl:strip-space elements="*" />
   <xsl:output indent="yes" method="xml" />

   <xsl:variable name="to-merge" select="document('input2.xml') | document('input3.xml')"/>

   <xsl:function name="a:id">
      <xsl:param name="ctx"/>
      <xsl:value-of select="concat($ctx/local-name(), $ctx/@id)"/>
   </xsl:function>   

   <xsl:key name="match" match="/schema/sequence/*" use="a:id(.)"/>

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

   <xsl:template match="*[count(. | key('match', a:id(.))) = count(key('match', a:id(.)))]">
    <xsl:copy>
           <xsl:apply-templates select="@* | node()"/>

           <xsl:variable name="id" select="a:id(.)"/>
           <xsl:for-each select="$to-merge">
              <xsl:apply-templates select="key('match', $id)/*"/>
           </xsl:for-each>
    </xsl:copy>
   </xsl:template>

</xsl:stylesheet>

您在 key 中定义合并点,并在 a:id 中定义合并匹配函数.只需将 a:id 函数带入您的谓词中,您就可以回退到 XSLT 1.0.

You define the merge point in the key and you define the merge match function in the a:id. You can fallback to XSLT 1.0 by just taking the a:id function into your predicates.

我的假设:

  • 您在领先"文档上运行转换并在该 to-merge 变量中对您的合并进行排序
  • 您有一个匹配点,它位于要合并的每个文档中的相同位置.自定义解决方案以从每个文档的不同点进行合并应该不难.
  • 节点通过 local-name()@id
  • 匹配
  • you run the transformation on the "leading" document and sequence your merges in that to-merge variable
  • you have a single match point that is located at the same spot in each document to be merged. it shouldn't be hard to customize the solution to merge from different points in each document.
  • the nodes match by local-name() and @id

这篇关于如何使用 xslt 连接两个或多个 xml 文件并保持顺序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆