2

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

我的设置文件如下所示:

设置.xml

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

 </xml>

主.xml

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

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

输出.xml

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

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

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

.

任何提示如何实现它?

4

3 回答 3

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

于 2012-06-15T18:06:46.273 回答
0

下面指出的这个 XSLT 适用于给定的文档。

请注意,我像您一样将Setting.xml的内容存储在一个变量中,但是,然后我将直接在我的查询中使用该变量。

这里的一个重要问题是,在matcha 的元素中template,不能使用变量。因此,我的模板匹配任何<title>元素,然后在<xsl:choose>元素中确定属性是否匹配设置文件中给定的任何值 - 如果匹配,<title>则输出中将省略该元素。

作为解释为什么 中的那个test属性<xsl:when>做它应该做的事情,想象一个比较someAttribute = someOtherAttribute不是作为一个限制,该属性someAttribute必须与该属性具有相同的值someOtherAttribute,而是作为一个条件,必须有任何两个属性someAttribute并且someOtherAttribute具有相同的值

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

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

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

    <xsl:template match="//title">
        <xsl:choose>
            <xsl:when test="(@titlename = $SuppressionSettings/xml/removenode/@titlename) and (subtitle/@subtitlename = $SuppressionSettings/xml/removenode/@subtitlename)"/>
            <xsl:otherwise>
                <xsl:copy>
                    <xsl:apply-templates select="node()|@*"/>
                </xsl:copy>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

</xsl:stylesheet>
于 2012-06-15T18:06:57.257 回答
0

这是一个更通用的答案,其中属性的名称没有硬编码到 XSLT 中。就像 OR 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>
于 2012-06-15T18:16:49.653 回答