使用 XML 样式表删除与另一个文件中的内容匹配的元素
Use XML Stylesheet to remove elements which match content in another file
我想像这样转换 xml 文件:
(input.xml)
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<DirectoryRef>
<Component Id="c1">
<File Source="!(PublishDir)\FileA" />
</Component>
<Component Id="c2">
<File Source="!(PublishDir)\FileB" />
</Component>
<Component Id="c3">
<File Source="!(PublishDir)\FileC" />
</Component>
<Component Id="c4">
<File Source="!(PublishDir)\FileD" />
</Component>
</DirectoryRef>
</Fragment>
<Fragment>
<ComponentGroup>
<ComponentRef Id="c1" />
<ComponentRef Id="c2" />
<ComponentRef Id="c3" />
<ComponentRef Id="c4" />
</ComponentGroup>
</Fragment>
</Wix>
这是热量的简化输出,wix(Windows安装程序XML)收割机。但这应该没什么区别。
从原来的 xml 中删除一些不需要的文件(包括 Component 和 ComponentRef 标签)。其中一些文件是预先知道的 (FileA),一些文件名在这样的文件中:
(filelist.xml)
<Files>
<File>FileB</File>
<File>FileC</File>
</Files>
结果应如下所示:
(output.xml)
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<DirectoryRef>
<Component Id="c4">
<File Source="!(PublishDir)\FileD" />
</Component>
</DirectoryRef>
</Fragment>
<Fragment>
<ComponentGroup>
<ComponentRef Id="c4" />
</ComponentGroup>
</Fragment>
</Wix>
删除事先已知的文件很简单,这是我目前所掌握的:
(stylesheet.xsl)
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:wix="http://schemas.microsoft.com/wix/2006/wi"
xmlns="http://schemas.microsoft.com/wix/2006/wi">
<!-- identity transform -->
<xsl:template match="@*|*">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:apply-templates select="*" />
</xsl:copy>
</xsl:template>
<xsl:output method="xml" indent="yes" />
<!-- remove files -->
<xsl:key name="file-search" match="wix:Component[substring(wix:File/@Source, string-length(wix:File/@Source) - 4) = 'FileA']" use="@Id"/>
<xsl:template match="wix:Component[key('file-search', @Id)]" />
<xsl:template match="wix:ComponentRef[key('file-search', @Id)]" />
</xsl:stylesheet>
但是如何从“filelist.xml”中删除文件呢?这是我尝试过的方法,但这不起作用(匹配中不允许使用变量)
<xsl:variable name="filelist" select="document('filelist.xml')"/>
<xsl:key name="file-search" match="wix:Component[contains($filelist, substring-after(wix:File/@Source, '\'))]" use="@Id"/>
XSLT 1.0 解决方案更可取,因为工具支持它,但我也可以使用带有一些额外连接的 XSLT 2.0。
在 XSLT 1.0 中执行此操作时面临的主要障碍是 (a) 键不能跨文档工作,以及 (b) 不能在匹配模式中使用变量。
也许你可以这样做:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:wix="http://schemas.microsoft.com/wix/2006/wi"
exclude-result-prefixes="wix">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="component-by-filename" match="wix:Component" use="substring-after(wix:File/@Source, '\')" />
<xsl:variable name="exclude-ids" select="key('component-by-filename', 'FileA')/@Id | key('component-by-filename', document('filelist.xml')/Files/File)/@Id "/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="wix:DirectoryRef | wix:ComponentGroup">
<xsl:copy>
<xsl:apply-templates select="*[not(@Id = $exclude-ids)]"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
我想像这样转换 xml 文件:
(input.xml)
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<DirectoryRef>
<Component Id="c1">
<File Source="!(PublishDir)\FileA" />
</Component>
<Component Id="c2">
<File Source="!(PublishDir)\FileB" />
</Component>
<Component Id="c3">
<File Source="!(PublishDir)\FileC" />
</Component>
<Component Id="c4">
<File Source="!(PublishDir)\FileD" />
</Component>
</DirectoryRef>
</Fragment>
<Fragment>
<ComponentGroup>
<ComponentRef Id="c1" />
<ComponentRef Id="c2" />
<ComponentRef Id="c3" />
<ComponentRef Id="c4" />
</ComponentGroup>
</Fragment>
</Wix>
这是热量的简化输出,wix(Windows安装程序XML)收割机。但这应该没什么区别。
从原来的 xml 中删除一些不需要的文件(包括 Component 和 ComponentRef 标签)。其中一些文件是预先知道的 (FileA),一些文件名在这样的文件中:
(filelist.xml)
<Files>
<File>FileB</File>
<File>FileC</File>
</Files>
结果应如下所示:
(output.xml)
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<DirectoryRef>
<Component Id="c4">
<File Source="!(PublishDir)\FileD" />
</Component>
</DirectoryRef>
</Fragment>
<Fragment>
<ComponentGroup>
<ComponentRef Id="c4" />
</ComponentGroup>
</Fragment>
</Wix>
删除事先已知的文件很简单,这是我目前所掌握的:
(stylesheet.xsl)
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:wix="http://schemas.microsoft.com/wix/2006/wi"
xmlns="http://schemas.microsoft.com/wix/2006/wi">
<!-- identity transform -->
<xsl:template match="@*|*">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:apply-templates select="*" />
</xsl:copy>
</xsl:template>
<xsl:output method="xml" indent="yes" />
<!-- remove files -->
<xsl:key name="file-search" match="wix:Component[substring(wix:File/@Source, string-length(wix:File/@Source) - 4) = 'FileA']" use="@Id"/>
<xsl:template match="wix:Component[key('file-search', @Id)]" />
<xsl:template match="wix:ComponentRef[key('file-search', @Id)]" />
</xsl:stylesheet>
但是如何从“filelist.xml”中删除文件呢?这是我尝试过的方法,但这不起作用(匹配中不允许使用变量)
<xsl:variable name="filelist" select="document('filelist.xml')"/>
<xsl:key name="file-search" match="wix:Component[contains($filelist, substring-after(wix:File/@Source, '\'))]" use="@Id"/>
XSLT 1.0 解决方案更可取,因为工具支持它,但我也可以使用带有一些额外连接的 XSLT 2.0。
在 XSLT 1.0 中执行此操作时面临的主要障碍是 (a) 键不能跨文档工作,以及 (b) 不能在匹配模式中使用变量。
也许你可以这样做:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:wix="http://schemas.microsoft.com/wix/2006/wi"
exclude-result-prefixes="wix">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="component-by-filename" match="wix:Component" use="substring-after(wix:File/@Source, '\')" />
<xsl:variable name="exclude-ids" select="key('component-by-filename', 'FileA')/@Id | key('component-by-filename', document('filelist.xml')/Files/File)/@Id "/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="wix:DirectoryRef | wix:ComponentGroup">
<xsl:copy>
<xsl:apply-templates select="*[not(@Id = $exclude-ids)]"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>