【问题标题】:How to get attribute values if they are not equal to some values?如果属性值不等于某些值,如何获取它们?
【发布时间】:2013-03-31 03:42:27
【问题描述】:

我有一个类似的 xml:

<movies>
    <movie name="aaa">
        ...
    </movie>
    <movie name="bbb">
        ...
    </movie>
    <movie name="ccc">
        ...
    </movie>
    <movie name="ddd">
        ...
    </movie>
    <movie name="eee">
        ...
    </movie>
</movies>

如果不是“aaa”、“bbb”或“ddd”,我想获取电影的名称。所以我希望我的输出是:

ccc
eee

因为我有几个限制,我认为不适合使用'xsl:if'..我写了我的xslt(我使用的是xslt 1.0):

<xsl:value-of select="movies/movie/@name[not(self::aaa) and not(self::bbb) and not(self:ddd)]"/>

但是编译器抱怨这句话有语法错误..我不知道为什么..

那么有人可以帮我解决这个问题吗?非常感谢!!

【问题讨论】:

    标签: xml xpath xslt-1.0


    【解决方案1】:

    试试这个 XPath 表达式:

    movies/movie[@name!='aaa' and @name!='bbb' and @name!='ddd']/@name
    

    或者这个:

    movies/movie/@name[.!='aaa' and .!='bbb' and .!='ddd']
    

    后者更短,但前者可以轻松扩展以检查其他返回,不仅是名称,还包括整个 &lt;movie&gt; 元素 - 只需删除最后的 /@name。或者,如果您想要第二个,只需在末尾添加 /..

    【讨论】:

    • 您好,谢谢您的回答。第一个解决方案奏效了。实际上我也想出了那个,但是由于我是 xslt 的新手,我想知道第一个 xpath 是否会使选择变慢?
    • @D.Q.: 不客气 :) 如果你真的需要 only name 属性,那么第二个表达式就是要走的路。如果您需要整个 &lt;movie&gt;,那么您必须使用类似这样的内容:&lt;foreach select="movies/movie[@name!='aaa' and ...]"&gt;Name: &lt;xsl:value-of select="@name"&gt;&lt;br /&gt; Description: &lt;xsl:value-of select="descr"&gt;&lt;/xsl:for-each&gt;。甚至更好:&lt;xsl:apply-templates select="movies/movie[@name!='aaa' and ...]" /&gt;。我无法进一步帮助您,因为我不知道您的 XML 的结构,也不知道您转换的预期结果。
    • 我明白你的意思 :) 还有一个问题,如果我有更多限制,例如我需要排除的名称数量有点大,比如 8 个或 10 个。有没有其他方法可以处理它,这样我就不会有一个很长的 xpath 表达式,这对于进一步扩展来说不是那么好。 ..
    • 不太...空的“忽略”模板。像这样:&lt;xsl:template select="movie" priority="1"&gt;..."process movie"...&lt;/template&gt; + &lt;xsl:template select="movie[@name='aaa' || @name='bbb' ...]" priority="2" /&gt;。使用 XSLT 2.0,您可以使用 index-of 函数。但请注意,都是关于语法的。核心是:被忽略的电影列表仍在您的 XSLT 中,这可能并不好。
    • 替代方案是: (+) 预处理您的输入 XML 以删除被忽略的电影 before XSLT 转换(这可能是最好的方法)。 (+) 对您的 XSLT 输出进行后处理,以在 转换之后过滤掉被忽略的视频。 (+) 即时生成 XSLT,根据来自被忽略的电影数据库的信息构建 XPath 表达式(如果批处理 XML 文件,这将大大降低性能)。
    【解决方案2】:

    考虑使用这样的表达式,以防比较的值太多:

    /*/movie[not(contains('|aaa|bbb|ddd|', concat('|', @name, '|)))]/@name
    

    这将选择作为 XSLT 文档顶部元素的子元素的任何 movie 元素的任何 name 属性,并且其值(name 属性)不是管道中的字符串之一- 分隔的字符串值列表"|aaa|bbb|ddd|"

    【讨论】:

    • @alex-shesterov,感谢您收看这个。现已更正。
    • 感谢@DimitreNovaatchev 提供了这个出色的解决方案!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-24
    • 1970-01-01
    • 2022-11-22
    • 2016-01-24
    • 1970-01-01
    • 2021-10-06
    • 2016-07-27
    相关资源
    最近更新 更多