我正在尝试从下面的XML中删除具有扩展名为“config”的File子元素的Component元素。我已经成功完成了这一部分,但我还需要删除与这些组件具有相同“Id”值的匹配ComponentRef元素。
<Fragment>
<DirectoryRef Id="MyWebsite">
<Component Id="Comp1">
<File Source="Web.config" />
</Component>
<Component Id="Comp2">
<File Source="Default.aspx" />
</Component>
</DirectoryRef>
</Fragment>
<Fragment>
<ComponentGroup Id="MyWebsite">
<ComponentRef Id="Comp1" />
<ComponentRef Id="Comp2" />
</ComponentGroup>
</Fragment>
基于其他SO答案,我提出了以下XSLT来删除这些组件元素:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:template match="Component[File[substring(@Source, string-length(@Source)- string-length('config') + 1) = 'config']]" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
不幸的是,这不会删除匹配的ComponentRef元素(即那些具有相同“Id”值的元素)。 XSLT将删除具有Id“Comp1”的组件,但不删除具有Id“Comp1”的ComponentRef。我如何使用XSLT 1.0实现这一目标?
答案 0 :(得分:4)
一种相当有效的方法是使用xsl:key
来识别配置组件的ID:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:key name="configComponent"
match="Component[File/@Source[substring(.,
string-length() - string-length('config') + 1) = 'config']]"
use="@Id" />
<xsl:template match="Component[key('configComponent', @Id)]" />
<xsl:template match="ComponentRef[key('configComponent', @Id)]" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:0)
这个怎么样?我对原文进行了一些小改动以简化操作(检查@source属性是否以'config'结尾更简单)。
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:template match="Component[substring(@Source, string-length(@Source) - 5) = 'config']" />
<xsl:template match="ComponentRef[//Component[substring(@Source, string-length(@Source) - 5) = 'config']/@Id = @Id]"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
这个模板匹配任何ComponentRef,它具有与前面模板匹配的Component相同的Id属性。有一点 - '//Component
'效率不高。您应该能够用更高效的东西替换它 - 我不知道您的XML结构