首先,让我说我喜欢阅读有关合并多个 XML 文件的许多技巧。我也很喜欢实施其中的很多。但是我还没有达到我的目标。
我不想简单地合并 XML 文件,以便在生成的 XML 文件中一个接一个地重复。我有需要合并重复元素的组:
<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 主机A、B和C的数据,而 XML 文件 2 具有 Windows 主机D、E和F的数据,则生成的 XML 应如下所示:
<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 来让它工作:
<?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 实例。不想那样。
有没有办法用最少的语法告诉 XSLT 如何做到这一点,或者我是否需要在 XSLT 文件中专门添加每个元素和子元素?
我应该检查一下。但是我继续使用了 collection() 并得到了一个使用 Saxon HE XSLT 处理器完美工作的解决方案。
但是我在 InfoPath 环境中运行,并且只有一个 XSLT 1.0 处理器。是否有人建议在 XSLT 1.0 环境中替换 collection() 命令?我可以以某种方式重新使用 document() 吗?
所以我现在有这个文件......
<?xml version="1.0" encoding="windows-1252"?>
<files>
<file name="CorralData1.xml"/>
<file name="CorralData2.xml"/>
</files>
...我与包含...的样式表一起使用
<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 根。我已经很接近了,但有些事情还是有点不对劲。