删除基于外部文件的元素

时间:2012-06-15 17:41:34

标签: xslt xslt-2.0

我有一个外部设置文件,其中有一些节点支持主xml文档的属性值。如果设置文件中存在属性值,我需要从mian xml文件中删除certian节点。

我的设置文件如下所示:

Setting.xml的

 <xml>
     <removenode titlename="abc" subtitlename="xyz"></removenode>
     <removenode titlename="dvd" subtitlename="dvd"></removenode>

 </xml>

main.xml中

<xml>
     <title titlename="abc">
         <subtitle subtitlename="xyz"></subtitle>
      </title>
      <title titlename="book">
          <subtitle subtitlename="book sub title"></subtitle>
      </title>
 </xml> 

需要一个查找setting.xml文件的脚本,如果在main.xml中找到titlename和subtitlename,则删除title元素。输出应为

的Output.xml

 <xml>
      <title titlename="book">
          <subtitle subtitlename="book sub title"></subtitle>
      </title>
 </xml> 

我尝试使用document来读取setting.xml文件但是无法找到如何在main.xml文件上进行匹配

 <xsl:variable name="SuppressionSettings" select="document('Setting.xml')" />
    <xsl:variable name="SuppressSetting" select="$SuppressionSettings/xml/removenode" />

任何提示如何实现它?

3 个答案:

答案 0 :(得分:2)

关键是使用标识/复制模式,并且在每次输出之前,检查抑制规则节点集不禁止当前(上下文)节点。

    <!-- get suppression settings -->
    <xsl:variable name='suppression_settings' select="document('http://www.mitya.co.uk/xmlp/settings.xml')/xml/removenode" />


    <!-- begin identity/copy -->

    <xsl:template match="node()|@*">
        <xsl:if test='not($suppression_settings[@titlename = current()/@titlename and @subtitlename = current()/subtitle/@subtitlename])'>
            <xsl:copy>
                <xsl:apply-templates select='node()|@*' />
            </xsl:copy>
        </xsl:if>
    </xsl:template>

你可以在这里运行它(参见输出源 - 省略'abc'标题节点):

http://www.xmlplayground.com/9oCYKp

答案 1 :(得分:0)

下面显示的XSLT适用于给定文档。

请注意,我正在将 Setting.xml 的内容存储在变量中,但是,我会在查询中直接使用该变量。

这里的一个重要问题是,在match的{​​{1}}元素中,无法使用变量。因此,我的模板匹配任何template元素,然后在<title>元素中确定属性是否与设置文件中给出的任何值匹配 - 如果是这样,<xsl:choose>元素将在输出

作为对<title>test属性为什么应该做的解释,假设<xsl:when>的比较不是属性{{1}的限制}必须与属性someAttribute = someOtherAttribute 具有相同的值,而是必须存在具有相同值的任意两个属性someAttributesomeOtherAttribute的条件< / em>的

someAttribute

答案 2 :(得分:0)

这是一个更通用的答案,其中属性的名称未硬编码到XSLT中。就像O. R. Mapper所指出的那样,在XSLT 1.0中你不能在match中使用变量引用,所以我将document()直接放在谓词中。这可能不如使用变量然后测试变量那么有效。

XSLT 1.0

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

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

    <xsl:template match="*[@* = document('setting.xml')/*/removenode/@*]"/>

</xsl:stylesheet>

XML输出(使用带有main.xml的2 xml文件作为输入)

<xml>
   <title titlename="book">
      <subtitle subtitlename="book sub title"/>
   </title>
</xml>