使用 xsl 删除 xml 中的自引用节点 [英] Removing a self referencing node in xml using xsl

查看:23
本文介绍了使用 xsl 删除 xml 中的自引用节点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是一个 XSL 新手并且在理解语法方面确实有困难.我想要实现的是从 xml 及其引用的节点中删除一个节点.此 xml 是通过运行 Heatdirectory(WIX 安装程序提供的工具)构建的.所以文件中的所有内容都是动态创建的.我知道的关于文件的一件事是我想删除引用的文件的名称.

I'm a XSL newb and have really trouble understanding the syntax. What I'm trying to achieve is to remove a node from the xml and its referenced node. This xml is build by running Heatdirectory, a tool provided with WIX Installer. So everything in the file is created dynamically. The one thing I know about the file, is the name of the file I want to remove the reference to.

这是 XML 示例:

<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <Fragment>
        <DirectoryRef Id="InstallFolder">
            <Component Id="cmpAEC985F4FAA50E51011E84E93A32F283" Guid="{3574FFF9-F47D-4A3F-A975-64D76546068A}">
                <File Id="fil9C01928D57F128482FD2A78A209FBF95" KeyPath="yes" Source="$(var.SourcePath)\AppSettings.config" />
            </Component>
            <Component Id="cmp10AE81284551BB54849628AE519965C7" Guid="{CF245728-B329-454E-A305-BE33FC818572}">
                <File Id="fil3F1ECB9AAE6412D0FDF9577B44764BA9" KeyPath="yes" Source="$(var.SourcePath)\CsvHelper.dll" />
            </Component>
            <Component Id="cmp596F6F97E366DDB8E0770EC1550C6CB5" Guid="{D8E5EF9E-CB20-4C40-BD02-D79364EC6518}">
                <File Id="filE48072B3494220F703E4B206DF9D2664" KeyPath="yes" Source="$(var.SourcePath)\CsvHelper.pdb" />
            </Component>
        </DirectoryRef>
    </Fragment>          
    <Fragment>
        <ComponentGroup Id="FileComponents">
            <ComponentRef Id="cmpAEC985F4FAA50E51011E84E93A32F283" />
            <ComponentRef Id="cmp10AE81284551BB54849628AE519965C7" />
            <ComponentRef Id="cmp596F6F97E366DDB8E0770EC1550C6CB5" />          
        </ComponentGroup>
    </Fragment>
</Wix>    

这是我的 XSLT,它删除了我想要删除的组件.

And this is my XSLT that removes the Component that I want to remove.

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt"
    exclude-result-prefixes="msxsl"
    xmlns:wix="http://schemas.microsoft.com/wix/2006/wi">
    <xsl:output method="xml" indent="yes" />
    <xsl:strip-space elements="*"/>
    <xsl:output omit-xml-declaration="yes"/>
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="wix:Component[contains(wix:File/@Source,'CsvHelper.pdb')]"/>
</xsl:stylesheet>

这就是我从中得到的.

<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
   <Fragment>
      <DirectoryRef Id="InstallFolder">
         <Component Id="cmpAEC985F4FAA50E51011E84E93A32F283" Guid="{3574FFF9-F47D-4A3F-A975-64D76546068A}">
            <File Id="fil9C01928D57F128482FD2A78A209FBF95" KeyPath="yes" Source="$(var.SourcePath)\AppSettings.config"/>
         </Component>
         <Component Id="cmp10AE81284551BB54849628AE519965C7" Guid="{CF245728-B329-454E-A305-BE33FC818572}">
            <File Id="fil3F1ECB9AAE6412D0FDF9577B44764BA9" KeyPath="yes" Source="$(var.SourcePath)\CsvHelper.dll"/>
         </Component>
      </DirectoryRef>
   </Fragment>
   <Fragment>
      <ComponentGroup Id="FileComponents">
         <ComponentRef Id="cmpAEC985F4FAA50E51011E84E93A32F283"/>
         <ComponentRef Id="cmp10AE81284551BB54849628AE519965C7"/>
         <ComponentRef Id="cmp596F6F97E366DDB8E0770EC1550C6CB5"/>
      </ComponentGroup>
   </Fragment>
</Wix>

但我也想删除引用已删除的 ComponentComponentRef.谁能告诉我怎么做?

But I aslo want to remove the ComponentRef referencing to the already removed Component. Can anyone tell me how to do this?

PS:我试图创建一个包含组件 ID 的变量(因为我不知道这一点,并且无法将其放入我的 XSLT 文件中).但是后来我无法进入 CompenentGroup 并删除 ComponentRef.

PS: I tried to create an variable containing the ID of the Component (since I dont know this, and cannot put this into my XSLT file). But then I could not get to the CompenentGroup and remove the ComponentRef.

推荐答案

将要删除的组件的 ID 存储在变量中.然后,您可以在任何需要查找某个 component 的地方引用它.您猜对了,这可能是解决方案.这是您的方法.

Store the ID of components that are to be deleted in a variable. Then, you can reference it wherever you need to find a certain component. You rightly guessed that this might be the solution. Here is how you can do it.

我向身份转换模板添加了第二个例外(即模板),以删除所述组件引用.

I added a second exception (i.e. a template) to the identity transform template that removes the said component reference.

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="msxsl"
xmlns:wix="http://schemas.microsoft.com/wix/2006/wi">

<xsl:output method="xml" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:output omit-xml-declaration="yes"/>

<xsl:variable name="del-id" select="//wix:Component[contains(wix:File/@Source,'CsvHelper.pdb')]/@Id"/>

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

<xsl:template match="wix:Component[@Id=$del-id]"/>

<xsl:template match="wix:ComponentRef[@Id=$del-id]"/>

</xsl:stylesheet>

EDIT:这是另一种在模板匹配中不使用变量的解决方案.不过时间有点长.

EDIT: Here is another solution without using variables in template matches. It's a bit longer though.

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="msxsl"
xmlns:wix="http://schemas.microsoft.com/wix/2006/wi">

<xsl:output method="xml" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:output omit-xml-declaration="yes"/>

<xsl:variable name="del-id" select="//wix:Component[contains(wix:File/@Source,'CsvHelper.pdb')]/@Id"/>

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

<xsl:template match="wix:ComponentGroup">
  <xsl:copy>
     <xsl:copy-of select="@*"/>
     <xsl:for-each select="wix:ComponentRef">
        <xsl:choose>
           <xsl:when test="@Id=$del-id"/>
           <xsl:otherwise>
              <xsl:copy>
                 <xsl:apply-templates select="node()|@*"/>
              </xsl:copy>
           </xsl:otherwise>
        </xsl:choose>
     </xsl:for-each>
  </xsl:copy>
</xsl:template>

<xsl:template match="wix:DirectoryRef">
  <xsl:copy>
     <xsl:copy-of select="@*"/>
     <xsl:for-each select="wix:Component">
        <xsl:choose>
           <xsl:when test="@Id=$del-id"/>
           <xsl:otherwise>
              <xsl:copy>
                 <xsl:apply-templates select="node()|@*"/>
              </xsl:copy>
           </xsl:otherwise>
        </xsl:choose>
     </xsl:for-each>
     <xsl:for-each select="wix:Directory">
        <xsl:copy>
           <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
     </xsl:for-each>
  </xsl:copy>
</xsl:template>

</xsl:stylesheet>

这篇关于使用 xsl 删除 xml 中的自引用节点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆