使用 XSLT 在组级别合并多个 XML 文件 [英] Merge multiple XML files at group levels with XSLT

查看:25
本文介绍了使用 XSLT 在组级别合并多个 XML 文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,让我说我很喜欢阅读有关合并多个 XML 文件的许多技巧.我也很喜欢实施其中的很多.但我还是没有达到我的目标.

First, let me say that I have enjoyed reading dozens of tips about merging multiple XML files. I've also enjoyed implementing a good number of them. But I still haven't achieved my goal.

我不想简单地合并 XML 文件,以便在生成的 XML 文件中一个接一个地重复.我有需要合并重复元素的组:

I don't want to simply merge XML files so that one is repeated after another in the resulting XML file. I have groups with repeating elements that need to each be merged:

<SAN>
  <EQLHosts>
    <WindowsHosts>
      <WindowsHost>
        more data and structures down here...
      </WindowsHost>
    </WindowsHosts>
    <LinuxHosts>
      <LinuxHost>
        ...and here...
      </LinuxHost>
    </LinuxHosts>
  </EQLHosts>
</SAN>

每个单独的 XML 文件都可能具有 Windows 和/或 Linux 主机.因此,如果 XML 文件 1 包含 Windows 主机 ABC 的数据,而 XML 文件 2 包含 Windows 主机D 的数据EF,生成的 XML 应如下所示:

Each of the individual XML files might have Windows and/or Linux hosts. So if XML file 1 has data for Windows host A, B and C, and XML file 2 has data for Windows hosts D, E and F, the resulting XML should look like:

<SAN>
  <EQLHosts>
    <WindowsHosts>
      <WindowsHost>
        <Name>A</Name>
      </WindowsHost>
      <WindowsHost>
        <Name>B</Name>
      </WindowsHost>
      <WindowsHost>
        <Name>C</Name>
      </WindowsHost>
      <WindowsHost>
        <Name>D</Name>
      </WindowsHost>
      <WindowsHost>
        <Name>E</Name>
      </WindowsHost>
      <WindowsHost>
        <Name>F</Name>
      </WindowsHost>
    </WindowsHosts>
    <LinuxHosts>
      <LinuxHost/>
    </LinuxHosts>
  </EQLHosts>
</SAN>

我已经使用这个 XSLT 来实现它:

I have used this XSLT, among others, to get this to work:

<?xml version="1.0"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

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

  <xsl:variable name="file1" select="document('CorralData1.xml')"/>
  <xsl:variable name="file2" select="document('CorralData2.xml')"/>
  <xsl:variable name="file3" select="document('CorralData3.xml')"/>

  <xsl:template match="/">
    <SAN>
      <xsl:copy-of select="/SAN/*"/>
      <xsl:copy-of select="$file1/SAN/*"/>
      <xsl:copy-of select="$file2/SAN/*"/>
      <xsl:copy-of select="$file3/SAN/*"/>
    </SAN>
  </xsl:template>

</xsl:stylesheet>

此文件生成一个组合的 XSLT,其中所有数据都正确地包含在树中,但包含多个 WindowsHosts 实例.不想那样.

This file produces a combined XSLT, with all data all the way down the tree included correctly, but with multiple instances of WindowsHosts. Don't want that.

有没有办法用最少的语法告诉 XSLT 如何做到这一点,或者我是否需要在 XSLT 文件中专门添加每个元素和子元素?

Is there a way to tell XSLT how to do this with a minimum of syntax, or do I need to add each element and sub-element specifically in the XSLT file?

我应该检查一下.但是我继续使用 collection() 并获得了一个使用 Saxon HE XSLT 处理器完美工作的解决方案.

I should have checked. But I went ahead and used collection() and got a solution to work perfectly using the Saxon HE XSLT processor.

但我在 InfoPath 环境中运行,并且只有一个 XSLT 1.0 处理器.有没有人建议在 XSLT 1.0 环境中替换 collection() 命令?我可以以某种方式重新使用 document() 吗?

But I'm running in an InfoPath environment, and there's only an XSLT 1.0 processor. Does anyone have a recommendation for replacing the collection() command in an XSLT 1.0 environment? Can I go back to using document() in some way?

所以我现在有了这个文件...

So I now have this file...

<?xml version="1.0" encoding="windows-1252"?>

<files>
    <file name="CorralData1.xml"/>
    <file name="CorralData2.xml"/>
</files>

...我使用的样式表包含...

...which I use with a stylesheet containing...

<xsl:variable name="windowsHosts" select="/SAN/WindowsHosts/WindowsHost"/>
<xsl:variable name="vmwareHosts" select="/SAN/VMwareHosts/VMwareHost"/>
<xsl:variable name="linuxHosts" select="/SAN/LinuxHosts/LinuxHost"/>

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

<xsl:template match="/">
    <xsl:for-each select="/files/file">
        <xsl:apply-templates select="document(@name)/SAN"/>
    </xsl:for-each>
    <SAN>
        <EQLHosts>
            <WindowsHosts>
                <xsl:for-each select="$windowsHosts">
                    <xsl:copy-of select="."/>
                </xsl:for-each>
            </WindowsHosts>
            <VMwareHosts>
                <xsl:for-each select="$vmwareHosts">
                    <xsl:copy-of select="."/>
                </xsl:for-each>                 
            </VMwareHosts>
            <LinuxHosts>
                <xsl:for-each select="$linuxHosts">
                    <xsl:copy-of select="."/>
                </xsl:for-each>                 
            </LinuxHosts>
        </EQLHosts>
    </SAN>
</xsl:template>

...但这让我得到了多个/SAN 根.我已经接近了,但还是有点不对劲.

...but this gets me multiple /SAN roots. I'm close but something's still a little off.

推荐答案

我为此操作使用了两个 XSLT 文件.第一个简单地附加所有文件:

I used two XSLT files for this operation. The first simply appends all the files:

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

<xsl:template match="/">
    <SAN>
        <xsl:apply-templates select="document('MainDataSource.xml')/SAN/*"/>
        <xsl:apply-templates select="document('CorralData1.xml')/SAN/*"/>
        <xsl:apply-templates select="document('CorralData2.xml')/SAN/*"/>
    </SAN>
</xsl:template>

第二个按组合并数据:

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

<xsl:template match="*">
    <SAN>
        <ClientProfile>
        </ClientProfile>
        <STACKMEMBERS>
            <xsl:for-each select="/SAN/STACKMEMBERS/STACKMEMBER">
                <xsl:copy-of select="."/>
            </xsl:for-each>
        </STACKMEMBERS>
        <Force10StackMembers>
            <xsl:for-each select="/SAN/Force10StackMembers/Force10StackMember">
                <xsl:copy-of select="."/>
            </xsl:for-each>
        </Force10StackMembers>
    </SAN>
</xsl:template>

这篇关于使用 XSLT 在组级别合并多个 XML 文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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