【问题标题】:Remove non-matching parent elements in XSL删除 XSL 中不匹配的父元素
【发布时间】:2012-04-27 19:38:28
【问题描述】:
  • 我需要删除所有Component 元素及其对应的ComponentRef 元素,其中Component 子元素File 属性Source 不是dll 文件?
  • 我有Source 字符串值的评估函数,即{substring(wix:File/@Source, string-length(wix:File/@Source) - 2)}='dll' 对包含dll 的Source 值返回true
  • 但是我不知道如何使用该函数删除最后两个Component元素(及其子元素)以及对应的最后两个ComponentRef元素(由Id属性映射)?李>

源 XML

<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <Fragment>
        <DirectoryRef Id="TARGETFOLDER">
            <Component Id="cmpA733DB49D89AC9CEA2EDFAAEE51992E7" Guid="{F3412A8F-5718-45AB-9E6F-7B802BCC0EED}">
                <File Source="$(var.WixSlave.TargetDir)\protobuf-net.dll" Id="fil910D6DB28382BAB5A9DF0ACBD5095ADE" KeyPath="yes" />
            </Component>
            <Component Id="cmpF1D751B9621E283AD7BDAA8BC6997338" Guid="{20C09DBB-C8D6-43CF-A9D6-C823850F86F6}">
                <File Source="$(var.WixSlave.TargetDir)\client.wyc" Id="fil7454A527FA7C3918A537EB96235C9F5F" KeyPath="yes"  />
            </Component>
            <Component Id="cmp8CDA926DD93F7CEFBF8FFF444D5828F4" Guid="{2243D9D8-C172-4FFE-AEBE-43659294E55D}">
                <File Source="$(var.WixSlave.TargetDir)\protobuf-net.pdb" Id="fil3EA19C07C51C4E31D37065B3A8620713" KeyPath="yes"  />
            </Component>
        </DirectoryRef>
    </Fragment>
    <Fragment>
        <ComponentGroup Id="Dlls">
            <ComponentRef Id="cmpA733DB49D89AC9CEA2EDFAAEE51992E7" />
            <ComponentRef Id="cmpF1D751B9621E283AD7BDAA8BC6997338" />
            <ComponentRef Id="cmp8CDA926DD93F7CEFBF8FFF444D5828F4" />
        </ComponentGroup>
    </Fragment>
</Wix>

功能失调的 XSLT 存根

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:wix="http://schemas.microsoft.com/wix/2006/wi" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="wix:File[{substring(wix:File/@Source, string-length(wix:File/@Source) - 2)}!='dll']"/>
</xsl:stylesheet>
  • 这个 XSLT 在很多方面都不起作用,首先是第二个 match 抱怨,我不确定这个表达式有什么问题..

  • 即使这样可行,您如何始终保留DirectoryRef,同时删除不匹配的Component 和子File 元素?

  • 完全没有删除对应的ComponentRef元素?

所需的 XML 输出

<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <Fragment>
        <DirectoryRef Id="TARGETFOLDER">
            <Component Id="cmpA733DB49D89AC9CEA2EDFAAEE51992E7" Guid="{F3412A8F-5718-45AB-9E6F-7B802BCC0EED}">
                <File Source="$(var.WixSlave.TargetDir)\protobuf-net.dll" Id="fil910D6DB28382BAB5A9DF0ACBD5095ADE" KeyPath="yes" />
            </Component>
        </DirectoryRef>
    </Fragment>
    <Fragment>
        <ComponentGroup Id="Dlls">
            <ComponentRef Id="cmpA733DB49D89AC9CEA2EDFAAEE51992E7" />
        </ComponentGroup>
    </Fragment>
</Wix>

【问题讨论】:

  • 它抱怨是因为它不喜欢{}。如果您从匹配中的 XPath 中删除了 {},它将让它运行

标签: xml xslt xpath wix xslt-1.0


【解决方案1】:

下面是我的做法:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:wix="http://schemas.microsoft.com/wix/2006/wi" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:key name="component-id" match="//wix:Component[substring(wix:File/@Source, string-length(wix:File/@Source) - 2) != 'dll']" use="@Id"/>

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

    <xsl:template match="wix:Component[@Id = key('component-id', @Id)/@Id]"/>

    <xsl:template match="wix:ComponentRef[@Id = key('component-id', @Id)/@Id]"/>
</xsl:stylesheet>

这个想法很简单。告诉 XSLT 处理器构建我们想要删除的那些组件节点的索引,然后使用匹配的模板抑制 xsl:copy。

【讨论】:

  • 在我的初始测试中完美运行!
  • 当然。您还可以考虑使用contains 进行“dll”测试。像这样的东西看起来比子字符串好一些:match="//wix:Component[not(contains(wix:File/@Source, 'dll'))].
  • 如果您想进一步优化它,您可以使用一个模板为您处理所有排除:&lt;xsl:template match="*[@Id = key('component-id', @Id)/@Id]"/&gt;。它假定您确实想要排除所有其他可能将其@Id 指向那些Components 的节点。
  • @PavelVeller:很好的答案,+1。请注意,以// 开头的匹配模式是没有用的:match="//wix:Component/someStepExpression" 等价于match="wix:Component/someStepExpression"。您也不需要转换中定义的默认命名空间,最好摆脱它。
猜你喜欢
  • 2011-10-16
  • 1970-01-01
  • 2019-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-25
  • 2023-03-05
  • 1970-01-01
相关资源
最近更新 更多