根据复杂条件从XML中删除元素

时间:2019-08-09 15:59:12

标签: xml xslt

我有一个如下所示的XML,我需要使用XSLT 1.0对其进行转换:

<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <Fragment>
        <DirectoryRef Id="Directory1">
            <Component Id="Component1">
                <File Id="File1" />
            </Component>
            <Component Id="Component2">
                <File Id="File2"/>
            </Component>
        </DirectoryRef>
        <DirectoryRef Id="Directory2">
            <Component Id="Component3">
                <File Id="File3" />
            </Component>
            <Component Id="Component4">
                <File Id="File4"/>
            </Component>
        </DirectoryRef>
    </Fragment>
    <Fragment>
        <ComponentGroup Id="Group">
            <ComponentRef Id="Component1" />
            <ComponentRef Id="Component2" />
            <ComponentRef Id="Component3" />
            <ComponentRef Id="Component4" />
        </ComponentGroup>
    </Fragment>
</Wix>

我需要与所有他的孩子一起删除ID为 Directory1 的元素,我已经完成了。但是我还需要删除其ID与我删除的<ComponentRef/> Directory1 的子代)的ID匹配的所有<Component/>元素。

因此,在这种情况下,所需的输出将是:

<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <Fragment>
        <DirectoryRef Id="Directory2">
            <Component Id="Component3">
                <File Id="File3" />
            </Component>
            <Component Id="Component4">
                <File Id="File4"/>
            </Component>
        </DirectoryRef>
    </Fragment>
    <Fragment>
        <ComponentGroup Id="Group">
            <ComponentRef Id="Component3" />
            <ComponentRef Id="Component4" />
        </ComponentGroup>
    </Fragment>
</Wix>

我已经遍历了<Component/>元素并将其删除,我需要一种方法来使用每个 Id 来匹配<ComponentRef/>元素并也将其删除。 / p>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:wi="http://schemas.microsoft.com/wix/2006/wi">
  <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
  <xsl:strip-space elements="*"/>

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

  <xsl:template match="*[wi:Component/parent::node()[@Name='Directory1']]"/>

</xsl:stylesheet>

1 个答案:

答案 0 :(得分:3)

尝试使用xsl:key ...

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:wi="http://schemas.microsoft.com/wix/2006/wi">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:key name="deleted_components" 
    match="wi:DirectoryRef[@Id='Directory1']/wi:Component" use="@Id"/>

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

  <xsl:template match="wi:DirectoryRef[@Id='Directory1']|
    wi:ComponentRef[key('deleted_components',@Id)]"/>

</xsl:stylesheet>

正在工作的小提琴:http://xsltfiddle.liberty-development.net/ej9EGdk