Mapforce产生奇怪之处

时间:2015-03-30 15:02:12

标签: xslt xpath map-force

我接手了一个用Mapforce生成的文件的项目。 我读了类似的东西:

*[local-name()='no_regnat' and namespace-uri()=''][not((not((translate(string(@xsi:nil), 'true ', '1') = '1')) and (string(.) = '')))]

似乎可以像这样写出

no_regnat[not((boolean(@xsi:nil) and (string(.) = '')))]

为什么要做前者?

1 个答案:

答案 0 :(得分:1)

让我们首先考虑表达式的左侧,

*[local-name()='no_regnat' and namespace-uri()='']

no_regnat

在大多数情况下,它们的含义完全相同,但在非常具体的情况下,它们不会产生相同的结果序列:

如果在XSLT 2.0样式表中定义xpath-default-namespace,则表达式不会提供相同的结果:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xpath-default-namespace="www.no_regnat.com">

    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="/">
        <results>
            <xsl:apply-templates/>
        </results>
    </xsl:template>

    <xsl:template match="*[local-name()='no_regnat' and namespace-uri()='']">
       <!--Or: template match="no_regnat"-->
        <xsl:copy-of select="."/>
    </xsl:template>

</xsl:stylesheet>

使用例如

测试上述内容
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:r="www.no_regnat.com">
    <no_regnat n="1"/>
    <r:no_regnat n="2"/>
    <other xmlns="www.no_regnat.com">
        <no_regnat n="3"/>
    </other>
</root>

并直接在线转换here

因此,我们需要查看这些表达式的上下文,以确定Mapforce是否确实生成了过于冗长的代码。


然后,第二个谓词:

translate(string(@nil), 'true ', '1')
在我看来,

真的奇怪。 translate()函数仅适用于单个字符,这就是作为translate()的第二个和第三个参数的字符串通常具有相同的长度的原因。第二个参数中第三个参数中没有对应字符的字符将转换为空字符串。

所以,这里的功能是将t映射到1,映射rue以及 (空白)什么也没有。 boolean()在这里更有用。


但请注意这些谓词的语义:

[not((not((translate(string(@xsi:nil), 'true ', '1') = '1')) and (string(.) = '')))]

装置

  

不允许xsi:nilfalse并且context元素的字符串值为空的情况

尽管

[not((boolean(@xsi:nil) and (string(.) = '')))]

装置

  

不允许xsi:niltrue并且context元素的字符串值为空的情况

最有可能的是,正确的约束是:if xsi:nil = 'true',那么context元素必须为空。