使用xsl删除xml中的自引用节点
我是一个XSL新手,在理解语法方面有很大的困难。 我试图实现的是从xml及其引用的节点中删除一个节点。此xml是通过运行WIX安装程序提供的工具Heatdirectory构建的。 因此,文件中的所有内容都是动态创建的。关于该文件,我知道的一件事是我要删除引用的文件的名称 以下是示例XML:使用xsl删除xml中的自引用节点,xml,xslt,wix,xslt-1.0,Xml,Xslt,Wix,Xslt 1.0,我是一个XSL新手,在理解语法方面有很大的困难。 我试图实现的是从xml及其引用的节点中删除一个节点。此xml是通过运行WIX安装程序提供的工具Heatdirectory构建的。 因此,文件中的所有内容都是动态创建的。关于该文件,我知道的一件事是我要删除引用的文件的名称 以下是示例XML: <?xml version="1.0" encoding="utf-8"?> <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<?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,它删除了我想要删除的组件
<?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>
但是我还想删除引用已经删除的组件的组件ref。
谁能告诉我怎么做
PS:我试图创建一个包含组件ID的变量(因为我不知道这个,也无法将其放入XSLT文件)。但是我无法访问componentgroup并删除ComponentRef。将要删除的组件的
ID
存储在变量中。然后,您可以在任何需要查找某个组件的地方引用它。您正确地猜测到这可能是解决方案。这是你可以做到的
我在标识转换模板中添加了第二个例外(即模板),该模板删除了所述组件引用
<?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>
编辑:这里是另一个不在模板匹配中使用变量的解决方案。不过要长一点
<?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>
在变量中存储要删除的组件的ID
。然后,您可以在任何需要查找某个组件的地方引用它。您正确地猜测到这可能是解决方案。这是你可以做到的
我在标识转换模板中添加了第二个例外(即模板),该模板删除了所述组件引用
<?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>
编辑:这里是另一个不在模板匹配中使用变量的解决方案。不过要长一点
<?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>
谢谢:)太简单了!!!。。但是,当你不理解语法时,这是非常困难的:)我在尝试这个时,最初缺少的是wix:component前面的双斜杠(//),在声明变量时:)所以现在到百万美元的问题。。。如何使用XSL 1.0实现这一点?导致编译器抱怨匹配中使用的变量。它说,它不支持中的变量。那么,请参阅百万美元答案的更新答案。让我知道它是否有效。上次更新删除了xml中的大部分代码。它将删除以下内容:。如果我在DirectoryRef节点中有更多的节点(其他类型),它也会删除这些。我的意思是它会删除ComponentGroup节点的ID属性。谢谢:)太简单了!!!。。但是,当你不理解语法时,这是非常困难的:)我在尝试这个时,最初缺少的是wix:component前面的双斜杠(//),在声明变量时:)所以现在到百万美元的问题。。。如何使用XSL 1.0实现这一点?导致编译器抱怨匹配中使用的变量。它说,它不支持中的变量。那么,请参阅百万美元答案的更新答案。让我知道它是否有效。上次更新删除了xml中的大部分代码。它将删除以下内容:。如果在DirectoryRef节点中有更多的节点(其他类型),它也会删除这些节点。我的意思是它会删除ComponentGroup节点的ID属性。