我已经成功创建了一个XSLT模板来复制一些元素,将一些元素的名称从一个XML文件更改为另一个XML文件。
但是,我无法弄清楚如何获取元素并将它们移动到XML结构的不同部分。
我想转换这个XML:
<Hosts>
<Clusters>
<Cluster>
<Nodes>
<WindowsHost/>
</Nodes>
</Cluster>
</Clusters>
</Hosts>
为:
<Hosts>
<WindowsHosts>
<WindowsHost/>
</WindowsHosts>
</Hosts>
我当前正在使用的XSLT包含:
<xsl:template match="/">
<xsl:apply-templates select="*"/>
</xsl:template>
<xsl:template match="/*">
<xsl:copy>
<xsl:apply-templates select="*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*">
<xsl:apply-templates select="*"/>
</xsl:template>
...然后重复模板,如:
<xsl:template match="/Hosts/Clusters/Cluster/Nodes/WindowsHost">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="/Hosts/Clusters/Cluster/Nodes/WindowsHost/SomeElement">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
等等。要复制的每个元素都有自己的模板,因为不会复制所有元素并更改某些元素名称。但我只是成功地更改了元素名称,而不是完整的XPath。
任何帮助都将不胜感激。
保
非常感谢您的回复。但我认为我的例子太简单了,试图说清楚。
我现有的XSLT为每个需要从一个XML复制到另一个XML的元素都有一个模板,所以有很多模板(差不多1000个),XSLT文件的开头确保默认情况下没有任何元素发生。长话短说,我在你的答案中尝试了这些技巧并没有成功,可能是因为情况并不像我给你看的那样。
要复制的元素有三种情况:
现有的XSLT文件适用于#1和#2。这是#3我无法上班。这里有更多的XSLT文件
<xsl:template match="/">
<xsl:apply-templates select="*"/>
</xsl:template>
<xsl:template match="/*">
<xsl:copy>
<xsl:apply-templates select="*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*">
<xsl:apply-templates select="*"/>
</xsl:template>
<xsl:template match="/SAN/ClientProfile">
<!-- copy element as is (working) -->
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="/SAN/ClientProfile/Name">
<!-- copy element but change its name (working) -->
<CompanyName>
<xsl:apply-templates/>
</CompanyName>
</xsl:template>
<xsl:template match="/SAN/EQLHosts/WindowsClusters/Cluster/ClusterNodes/WindowsHost">
<!-- copy to different part of schema (not working) -->
<WindowsHost>
<xsl:apply-templates/>
</WindowsHost>
</xsl:template>
所以,我想将/SAN/EQLHosts/WindowsClusters/Cluster/ClusterNodes/WindowsHost
更改为/SAN/EQLHosts/WindowsHosts/WindowsHost
。此元素的所有子元素的处理方式与已复制元素的处理方式相同。
我希望我的澄清清楚。如果这些信息改变了你的答案,或者我是否只是密集,请告诉我。
保
答案 0 :(得分:1)
看起来你真的不动了什么;只是忽略一些元素并添加一个新的WindowsHosts
元素。尝试使用一个indentity transform并更改xsl:apply-templates
从/*
模板中选择的内容。
如果您仍需要重命名其他元素,只需添加一个与该元素特定匹配的新模板即可。身份转换将复制现有元素而不修改它们,因此您不必为每个元素都有一个模板。
示例:
XML输入
<Hosts>
<Clusters>
<Cluster>
<Nodes>
<WindowsHost/>
</Nodes>
</Cluster>
</Clusters>
</Hosts>
XSLT 1.0
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*">
<xsl:copy>
<WindowsHosts>
<xsl:apply-templates select="@*|Clusters/Cluster/Nodes/WindowsHost"/>
</WindowsHosts>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
输出
<Hosts>
<WindowsHosts>
<WindowsHost/>
</WindowsHosts>
</Hosts>
修改强>
这是一个包含重命名的示例。它使用上面的输入产生相同的输出......
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<!--Identity Transform-->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*">
<xsl:copy>
<!--Start your select at the first element you need to output and/or modify.-->
<xsl:apply-templates select="@*|Clusters/Cluster"/>
</xsl:copy>
</xsl:template>
<!--Example rename-->
<xsl:template match="Cluster">
<WindowsHosts>
<xsl:apply-templates select="@*|Nodes/WindowsHost"/>
</WindowsHosts>
</xsl:template>
</xsl:stylesheet>
编辑#2
所以,我想改变
/SAN/EQLHosts/WindowsClusters/Cluster/ClusterNodes/WindowsHost
来/SAN/EQLHosts/WindowsHosts/WindowsHost
。这个元素的所有孩子 将以与已经存在的元素相同的方式处理 被复制。
在这种情况下,您要从WindowsHost
...
EQLHosts
<xsl:template match="EQLHosts">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<WindowsHosts>
<xsl:apply-templates select="WindowsClusters/Cluster/ClusterNodes/WindowsHost"/>
</WindowsHosts>
</xsl:copy>
</xsl:template>
如果您需要输出EQLHosts
中的其他子项,则可以将其添加到第一个xsl:apply-templates
。类似的东西:
<xsl:apply-templates select="@*|*[not(name()='WindowsClusters')]"/>
答案 1 :(得分:0)
由于将Daniel的答案与现有的XSLT文件结合使用,我创建了一个单独的XSLT文件,只是将这些元素移动到XML结构中的新位置。
此文件看起来像......
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="EQLHosts">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<WindowsHosts>
<xsl:apply-templates select="WindowsClusters/Cluster/ClusterNodes/WindowsHost"/>
<xsl:apply-templates select="WindowsClusters/Cluster/VirtualMachines/WindowsHost"/>
<xsl:apply-templates select="WindowsHosts/WindowsHost"/>
</WindowsHosts>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
......完美无缺。这个XSLT文件包含所有元素,同时移动一些元素。
我现有的XSLT文件排除所有元素,只复制指定的元素。因此,我认为拥有两个XSLT文件并不是一个坏主意,一个是一个接一个地运行。
除非有办法将它们合并,否则我会将它们保留为两个。