字符串序列与空字符串的比较

Comparison between string sequence and empty string

我已经有了答案,但我想了解它为什么有效,但我还不确定。

我有以下填充了匹配项的变量:

 <xsl:variable name="invalid_characters" as="xs:string*">
   <xsl:analyze-string select="$urlToValidate" regex="{$regex}">
     <xsl:matching-substring>                
       <xsl:value-of select="."/>
     </xsl:matching-substring>
   </xsl:analyze-string>        
 </xsl:variable>            

然后我希望模板对那个变量做一些事情,以防它不是 null 或空的,所以我这样问:

<xsl:if test="not($invalid_characters='')">
   <error>The error</error>
</xsl:if>

问题是 if 始终为真...即使变量为空,我也必须这样做才能工作

<xsl:if test="$invalid_characters!=''">
   <error>The error</error>
</xsl:if>

困扰我的是,如果我这样做:

<xsl:if test="$invalid_characters=''">
   <error>The error</error>
</xsl:if>

if 语句执行了它应该执行的操作,所以,有人知道为什么我首先执行的操作没有按预期执行吗?

提前致谢:)

--- 编辑:有人说这个问题很难理解所以我举个例子。

在这里您可以看到带有两个 if 语句和输入的 xslt 的完整示例。

xsl:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">

<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>    

<xsl:template match="/">
    <xsl:apply-templates select="//@*"/>
</xsl:template>

<xsl:template match="@href[not(../scope) or     ../scope='local']|@conref|@conrefend">
    <xsl:variable name="urlToValidate" select="if(substring-before(.,'#')='')
                                     then .
                                     else substring-before(.,'#')"/>        
    <xsl:variable name="regex">[$&apos;%\*\./=\&lt;&gt;_\(\)\[\]:;,\^~\?|@!\+&amp;\}\{]</xsl:variable>        
    <xsl:variable name="invalid_characters" as="xs:string*">
        <xsl:analyze-string select="$urlToValidate" regex="{$regex}">
            <xsl:matching-substring>                
                <xsl:value-of select="."/>
            </xsl:matching-substring>
        </xsl:analyze-string>        
    </xsl:variable>    
    <xsl:if test="not($invalid_characters='')">
        <error1>
            <xsl:value-of select="."/>
        </error1>            
    </xsl:if>               
    <xsl:if test="$invalid_characters!=''">
        <error2>
            <xsl:value-of select="."/>
        </error2>            
    </xsl:if>        
</xsl:template>    
</xsl:stylesheet>

这是输入:

<links>
<image conrefend="GUID-6A680D85-10FA-4BCC-B57D-B5138ABE6A59" /> 
<image conrefend="GUID-1F14088D-4376-46FF-AE6F-937C2AAF5A43" /> 
<image conrefend="GUID-BB4F234D-3584-4B92-B9CB-D91FBD913B8D#GUID-BB4F234D-584-4B92-B9CB-D91FBD913B8D/MSCPDR1" />
<image conrefend="GUID-6E03D2D4-3FA9-4437-8689-06B873FB56CB" />
<image conrefend="GUID-C97E0253-73C1-4A27-B43E-7A913400BBB8" />
<image conrefend="COPY-GUI'D-86241639-37CD-4CF7-A7AA-F09F4A763944"/>
<image conrefend="COPY-GUID-86241639-37CD-4CF7-A7AA-F09F4A763944"/>
<image conref="COPY-GUID/*+-862416}39-37CD-4CF7-A7AA-F09F4A763944" />
<image conrefend="COPY-GUID-8624163{9-37CD-4CF7-A7AA-F09F4A763944"/>  
<image href="COPY-GUID-8624163&lt;9-37CD-4CF7-A7AA-F09F4A763944" scope="local"/> 
<image href="COPY-GUID-8624163~9-37CD-4CF7-A7AA-F09F4A763944" scope="local"/>    
</links>

这是我得到的结果:

<error1>GUID-6A680D85-10FA-4BCC-B57D-B5138ABE6A59</error1>
<error1>GUID-1F14088D-4376-46FF-AE6F-937C2AAF5A43</error1>
<error1>GUID-BB4F234D-3584-4B92-B9CB-D91FBD913B8D#GUID-BB4F234D-3584-4B92-B9CB-D91FBD913B8D/MSCPDR1</error1>
<error1>GUID-6E03D2D4-3FA9-4437-8689-06B873FB56CB</error1>
<error1>GUID-C97E0253-73C1-4A27-B43E-7A913400BBB8</error1>
<error1>COPY-GUI'D-86241639-37CD-4CF7-A7AA-F09F4A763944</error1>
<error2>COPY-GUI'D-86241639-37CD-4CF7-A7AA-F09F4A763944</error2>
<error1>COPY-GUID-86241639-37CD-4CF7-A7AA-F09F4A763944</error1>
<error1>COPY-GUID/*+-862416}39-37CD-4CF7-A7AA-F09F4A763944</error1>
<error2>COPY-GUID/*+-862416}39-37CD-4CF7-A7AA-F09F4A763944</error2>
<error1>COPY-GUID-8624163{9-37CD-4CF7-A7AA-F09F4A763944</error1>
<error2>COPY-GUID-8624163{9-37CD-4CF7-A7AA-F09F4A763944</error2>
<error1>COPY-GUID-8624163&lt;9-37CD-4CF7-A7AA-F09F4A763944</error1>
<error2>COPY-GUID-8624163&lt;9-37CD-4CF7-A7AA-F09F4A763944</error2>
<error1>COPY-GUID-8624163~9-37CD-4CF7-A7AA-F09F4A763944</error1>
<error2>COPY-GUID-8624163~9-37CD-4CF7-A7AA-F09F4A763944</error2>

如您所见,每个条目都有一个 error1 标签,而 error2 标签只用于那些应该出现的情况。

为什么第一次比较没有像我认为的那样起作用?

以下对您无效

<xsl:if test="not($invalid_characters='')">
    <error>The error</error>
</xsl:if>

因为,一个空序列不等于任何东西(它也不等于另一个空序列)。试试,<xsl:value-of select="() = ()"/>,你会得到 false。 因此,对于一个空序列,条件总是 true.

为什么这有效

<xsl:if test="$invalid_characters!=''">
    <error>The error</error>
</xsl:if>

是因为,对于一个空序列,这总是被评估为 false。尝试:<xsl:value-of select="() != ()"/> 你会得到 false(空序列既不等于也不不等于任何东西)。 这里的序列,如果至少包含一个不是空字符串的项目,则将 return true。因此,将无法完成空字符串或空字符串的工作。

您的变量是一个序列,包含零个、一个或多个字符串(每个字符串是否为空取决于特定的正则表达式)。

空序列与空字符串的比较:

空序列和空字符串不是一回事;空序列和空字符串之间的比较总是 return false:

() = ''    false
() != ''   false

单项序列与空字符串的比较:

包含单个字符串的序列等同于该字符串(参见 XPath Data Model),因此它可以 为空字符串 或者(异或) 不同于空串:

('') = ''      true
('') != ''     false

('foo') = ''   false
('foo') != ''  true

多项序列与空字符串的比较:

如果两个序列至少有一个共同项,则为 "equal",如果它们至少有一个不同项,则为 "different"。因此,两个序列可能两者相等不同

这也适用于比较多项目序列和字符串,因为我们已经看到字符串等同于仅包含该字符串的序列:

('', '') = ''           true
('', '') != ''          false

('foo', 'bar') = ''     false
('foo', 'bar') != ''    true

('foo', '') = ''        true
('foo', '') != ''       true

结论:

在处理序列时,检查 $a != $b 不等同于 检查 not($a = $b)