Mapforce 产生异常
Mapforce generates oddities
我接手了一个项目,其中包含使用 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(.) = '')))]
为什么是前者?
让我们首先考虑表达式的左侧,
*[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
,以及映射 r
、u
和 e
以及 </code>(空格)什么都没有。 <code>boolean()
在这里更有用。
但要注意这些谓词的语义:
[not((not((translate(string(@xsi:nil), 'true ', '1') = '1')) and (string(.) = '')))]
表示
do not allow cases where xsi:nil
is false
and the string value of the context element is empty
鉴于
[not((boolean(@xsi:nil) and (string(.) = '')))]
表示
do not allow cases where xsi:nil
is true
and the string value of the context element is empty
最有可能的是,正确的约束是:如果 xsi:nil = 'true'
,则上下文元素必须为空。
我接手了一个项目,其中包含使用 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(.) = '')))]
为什么是前者?
让我们首先考虑表达式的左侧,
*[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
,以及映射 r
、u
和 e
以及 </code>(空格)什么都没有。 <code>boolean()
在这里更有用。
但要注意这些谓词的语义:
[not((not((translate(string(@xsi:nil), 'true ', '1') = '1')) and (string(.) = '')))]
表示
do not allow cases where
xsi:nil
isfalse
and the string value of the context element is empty
鉴于
[not((boolean(@xsi:nil) and (string(.) = '')))]
表示
do not allow cases where
xsi:nil
istrue
and the string value of the context element is empty
最有可能的是,正确的约束是:如果 xsi:nil = 'true'
,则上下文元素必须为空。