0

我已经成功地创建了一个 XSLT 模板来复制一些元素,改变一些元素的名称,从一个 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 文件的开头确保默认情况下任何元素都不会发生任何事情。长话短说,我尝试了您回答中的技术但没有成功,可能是因为情况与我向您展示的情况不完全一样。

复制元素有三种情况:

  1. 照原样复制
  2. 复制但更改元素名称
  3. 复制到架构中的不同位置

现有的 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. 该元素的所有子元素的处理方式与已被复制的元素相同。

我希望我的澄清很清楚。请让我知道此信息是否会改变您的答案,或者我是否只是过于密集。

保罗

4

2 回答 2

1

看起来你并没有真正移动任何东西;只是忽略一些元素并添加一个新WindowsHosts元素。尝试进行单个缩进转换并更改您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')]"/>
于 2013-05-23T23:53:18.060 回答
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 文件并一个接一个地运行并不是一个坏主意。

除非有办法将它们结合起来,否则我会将它们保留为两个。

于 2013-05-28T19:26:41.770 回答