使用XSLT复制XML删除某些节点

时间:2013-10-22 11:28:24

标签: xml xslt xpath xslt-2.0 xmlspy

我知道它已经在XSL: how to copy a tree, but removing some nodes?之前得到了解答,但是我有一个更复杂的XML文件,并且效果不佳。

这整个XML和XSLT对我来说都是新的,我的老板给我分配了一项任务,即将XML(OVF文件从VMWare)转换为另一个,删除一些节点,添加其他节点和更新信息。我有两个XML文件,我的任务是设计将转换它们的XSLT。

这是原始的XML:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Built using IBM Image Construction and Composition Tool, version: 1.2.0.1-20121129-1310-255 on: Oct 18, 2013 12:14:22 -->
<Envelope
    xmlns="http://schemas.dmtf.org/ovf/envelope/1" xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1"
    xmlns:cloudburst="http://www.ibm.com/websphere/rainmaker/2009/3" xmlns:rasd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData"
    xmlns:vssd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData" cloudburst:name="POSTGRES-9.2.4-RHEL-64.X64.xxx.xxx"
    cloudburst:version="1.0.0" cloudburst:build="sample" cloudburst:serviceLevel="0"
    cloudburst:description="BASEIMAGE FOR POSTGRESQL 9.2.4" cloudburst:symbolicName="POSTGRES-9.2.4-RHEL-64.X64.xxx.xxx">
  <References>
    <File ovf:href="en-US-bundle.msg" ovf:id="en-US-bundle.msg" ovf:size="18526"/>
    <File ovf:href="de-DE-bundle.msg" ovf:id="de-DE-bundle.msg" ovf:size="20687"/>
    <File ovf:href="es-ES-bundle.msg" ovf:id="es-ES-bundle.msg" ovf:size="20364"/>
    <File ovf:href="fr-FR-bundle.msg" ovf:id="fr-FR-bundle.msg" ovf:size="20534"/>
    <File ovf:href="it-IT-bundle.msg" ovf:id="it-IT-bundle.msg" ovf:size="20138"/>
    <File ovf:href="ja-JP-bundle.msg" ovf:id="ja-JP-bundle.msg" ovf:size="23116"/>
    <File ovf:href="ko-KR-bundle.msg" ovf:id="ko-KR-bundle.msg" ovf:size="19114"/>
    <File ovf:href="pt-BR-bundle.msg" ovf:id="pt-BR-bundle.msg" ovf:size="20204"/>
    <File ovf:href="zh-CN-bundle.msg" ovf:id="zh-CN-bundle.msg" ovf:size="16875"/>
    <File ovf:href="zh-TW-bundle.msg" ovf:id="zh-TW-bundle.msg" ovf:size="18395"/>
    <File ovf:href="Automation.topology" ovf:id="Automation.topology" ovf:size="196121"/>
    <File ovf:href="Semantic.topology" ovf:id="Semantic.topology" ovf:size="34496"/>
    <File ovf:href="RedHat6-4-64-Base-PRB-HARDENEDv1-1-bis.vmdk" ovf:id="RedHat6-4-64-Base-PRB-HARDENEDv1-1-bis.vmdk"
        ovf:size="3129636864"/>
    <File ovf:href="RedHat6-4-64-Base-PRB-HARDENEDv1-1-bis_1.vmdk" ovf:id="RedHat6-4-64-Base-PRB-HARDENEDv1-1-bis_1.vmdk"
        ovf:size="470930944"/>
    <File ovf:href="RedHat6-4-64-Base-PRB-HARDENEDv1-1-bis_2.vmdk" ovf:id="RedHat6-4-64-Base-PRB-HARDENEDv1-1-bis_2.vmdk"
        ovf:size="597504"/>
    <File ovf:href="RedHat6-4-64-Base-PRB-HARDENEDv1-1-bis_3.vmdk" ovf:id="RedHat6-4-64-Base-PRB-HARDENEDv1-1-bis_3.vmdk"
        ovf:size="8147968"/>
    <File ovf:href="default1382090373335.xml" ovf:id="default1382090373335.xml"
        ovf:size="17914" cloudburst:part2Definition="true"/>
    <File ovf:href="default1382090373335C.xml" ovf:id="default1382090373335C.xml"
        ovf:size="15854" cloudburst:part2Definition="true"/>
  </References>
</Envelope>

(这只是第一个父节点,下面还有更多,但我认为知道如何做第一部分,其余部分会更容易)

它必须如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Built using IBM Image Construction and Composition Tool, version: 1.2.0.1-20121129-1310-255 on: Oct 18, 2013 12:14:22 -->
<Envelope
    xmlns="http://schemas.dmtf.org/ovf/envelope/1" xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1"
    xmlns:cloudburst="http://www.ibm.com/websphere/rainmaker/2009/3" xmlns:rasd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData"
    xmlns:vssd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData" cloudburst:name="POSTGRES-9.2.4-RHEL-64.X64.xxx.xxx"
    cloudburst:version="1.0.0" cloudburst:build="sample" cloudburst:serviceLevel="0"
    cloudburst:description="BASEIMAGE FOR POSTGRESQL 9.2.4" cloudburst:symbolicName="POSTGRES-9.2.4-RHEL-64.X64.xxx.xxx">
  <References>
    <File ovf:href="en-US-bundle.msg" ovf:id="en-US-bundle.msg" ovf:size="18526"/>
    <File ovf:href="Automation.topology" ovf:id="Automation.topology" ovf:size="196121"/>
    <File ovf:href="Semantic.topology" ovf:id="Semantic.topology" ovf:size="34496"/>
    <File ovf:href="RedHat6-4-64-Base-PRB-HARDENEDv1-1-bis.vmdk" ovf:id="RedHat6-4-64-Base-PRB-HARDENEDv1-1-bis.vmdk"
        ovf:size="3129636864"/>
    <File ovf:href="RedHat6-4-64-Base-PRB-HARDENEDv1-1-bis_1.vmdk" ovf:id="RedHat6-4-64-Base-PRB-HARDENEDv1-1-bis_1.vmdk"
        ovf:size="470930944"/>
    <File ovf:href="RedHat6-4-64-Base-PRB-HARDENEDv1-1-bis_2.vmdk" ovf:id="RedHat6-4-64-Base-PRB-HARDENEDv1-1-bis_2.vmdk"
        ovf:size="597504"/>
    <File ovf:href="RedHat6-4-64-Base-PRB-HARDENEDv1-1-bis_3.vmdk" ovf:id="RedHat6-4-64-Base-PRB-HARDENEDv1-1-bis_3.vmdk"
        ovf:size="8147968"/>
    <File ovf:href="default1382090373335.xml" ovf:id="default1382090373335.xml"
        ovf:size="17914" cloudburst:part2Definition="true"/>
    <File ovf:href="default1382090373335C.xml" ovf:id="default1382090373335C.xml"
        ovf:size="15854" cloudburst:part2Definition="true"/>
  </References>
</Envelope>

正如您所看到的,我要做的是选择包含“bundle”的所有File个节点并除去它们,除了第一个(包含en-US)。 我写的选择它们的xPath是

/Envelope/References/File[contains(@ovf:href, 'bundle')][position()>1]

(我遇到了麻烦,因为 - 我认为 - 所有命名空间,但我在Altova XMLspy中尝试过它并且它完美无缺地工作)

由于我从未使用XSL编程,它与我所知道的有点不同(主要是C,Java,PHP,VB.net ......)但我知道HTML所以基本结构是我所知道的。

所以,我的问题是,XSL会复制整个XML但忽略File个节点的子集会是什么样的?

这不起作用,我从之前链接的那个答案中复制了

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" >

    <xsl:template match="node() | @*">
        <xsl:copy>
            <xsl:apply-templates select="node() | @*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="/Envelope/References/File[contains(@href, 'bundle')][position()>1]"/> <!-- this empty template will remove them -->
</xsl:stylesheet>

我认为如果我使用XSL v1或v2并不重要,实际上我不知道它们之间的区别:D

由于

1 个答案:

答案 0 :(得分:1)

这是因为命名空间。在输入XML中,您已使用xmlns="http://schemas.dmtf.org/ovf/envelope/1 ovf 命名空间xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1定义了默认命名空间。 File个元素属于默认命名空间,@href属性属于 ovf 命名空间。这些命名空间恰好相同。

您需要在XSLT中定义相同的命名空间,然后使用该命名空间匹配元素和属性。 (请注意,您可以随意调用命名空间,只要其值与输入中的相应值匹配。我在下面将其称为 ns 。)

以下样式表将删除包含“bundle”的第一个File节点以外的所有节点。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                xmlns:ns="http://schemas.dmtf.org/ovf/envelope/1">
  <xsl:output method="xml" indent="yes" />
  <xsl:strip-space elements="*"/>

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

  <!-- this empty template will remove them -->
  <xsl:template match="ns:Envelope/ns:References/ns:File[contains(@ns:href, 'bundle')][position()>1]"/>
</xsl:stylesheet>