如何确认一个字符串序列是另一个字符串序列的子集?
How do I confirm that one string sequence is a subset of another?
我不知道如何确定一组字符串 (xs:string*) 是否是一组参考字符串的子集。
我假设节点集操作适用于 xs:string*,但它们适用于类型 node(),而不适用于 xs:string。我也尝试了更简单的 contains() 函数,它只适用于单个字符串,不适用于字符串序列。
<?xml version="1.0"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="permitted" select="tokenize('1,2,3,278', ',')"/>
<xsl:template match="/">
<html>
<xsl:apply-templates/>
</html>
<xsl:template match="experience">
<xsl:variable name="test" select="tokenize(ids, ', ')"/>
<xsl:if test="count($permitted | $test)=count($permitted)">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
我明白了:
错误:文档顺序排序器所需的项目类型是 node();提供的值具有项目类型 xs:string
如果您使用(XPath 2 及更高版本)every $s in $test satisfies $s = $permitted
,那么我认为您的检查应该适用于像字符串这样的原子值序列。
替代方案:count($test) = count($test[. = $permitted])
使用:
not($vTest[not(. = $vPermitted)])
基于 XSLT 的验证:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:variable name="vPermitted" as="xs:string*" select="'1', '2', '3', '278'"/>
<xsl:variable name="vTest1" as="xs:string*" select="'1', '2', '3'"/>
<xsl:variable name="vTest2" as="xs:string*" select="'1', '2', '3', '4'"/>
<xsl:template match="/">
<xsl:sequence select="not($vTest1[not(. = $vPermitted)])"/>
<xsl:sequence select="not($vTest2[not(. = $vPermitted)])"/>
</xsl:template>
</xsl:stylesheet>
当上述转换应用于任何 XML 文档(未使用)时,将评估两个 XPath 表达式并输出它们正确的、想要的结果:
true false
注意:
即使在没有序列概念的 XPath 1.0 (XSLT 1.0) 中也可以使用完全相同的表达式,但可以使用节点集代替。
解释:
这是“Principle of Double Negation”。这个原理被认为是经典逻辑中的一个思维规律。罗素和怀特海在《数学原理》中将该原理表述为命题逻辑定理:
"This is the principle of double negation, i.e. a proposition is equivalent of the falsehood of its negation."
最佳实施 -- 接近 O(N)
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:variable name="vPermitted" as="map(xs:string, xs:boolean)" select=
"map{'1' : true(), '2' : true(), '3' : true(), '278' : true()}"/>
<xsl:variable name="vTest1" as="xs:string*" select="'1', '2', '3'"/>
<xsl:variable name="vTest2" as="xs:string*" select="'1', '2', '3', '4'"/>
<xsl:template match="/">
<xsl:sequence select="not($vTest1[not($vPermitted(.))])"/>
<xsl:sequence select="not($vTest2[not($vPermitted(.))])"/>
</xsl:template>
</xsl:stylesheet>
当上述转换应用于任何 XML 文档(未使用)时,将评估两个 XPath 表达式并输出它们正确的、想要的结果:
true false
虽然前面的表达式(包括当前接受的答案中的表达式)都有时间复杂度O(M*N)
,但上面的XPath 3.1 expression uses a pre-populated (global / created only once) map所以任何检查如果一个键存在需要常数时间——因此这个算法的总时间复杂度是O(N)
这里我们做出合理的假设,即正在使用的 XPath 引擎具有经过良好优化的地图实现,例如基于哈希表的地图实现
集合操作不适用于字符串,但序列操作可以。您的尝试:
<xsl:if test="count($permitted | $test)=count($permitted)">
可以重写为:
<xsl:if test="deep-equal(distinct-values(($permitted, $test)), $permitted)">
我不知道如何确定一组字符串 (xs:string*) 是否是一组参考字符串的子集。
我假设节点集操作适用于 xs:string*,但它们适用于类型 node(),而不适用于 xs:string。我也尝试了更简单的 contains() 函数,它只适用于单个字符串,不适用于字符串序列。
<?xml version="1.0"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="permitted" select="tokenize('1,2,3,278', ',')"/>
<xsl:template match="/">
<html>
<xsl:apply-templates/>
</html>
<xsl:template match="experience">
<xsl:variable name="test" select="tokenize(ids, ', ')"/>
<xsl:if test="count($permitted | $test)=count($permitted)">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
我明白了:
错误:文档顺序排序器所需的项目类型是 node();提供的值具有项目类型 xs:string
如果您使用(XPath 2 及更高版本)every $s in $test satisfies $s = $permitted
,那么我认为您的检查应该适用于像字符串这样的原子值序列。
替代方案:count($test) = count($test[. = $permitted])
使用:
not($vTest[not(. = $vPermitted)])
基于 XSLT 的验证:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:variable name="vPermitted" as="xs:string*" select="'1', '2', '3', '278'"/>
<xsl:variable name="vTest1" as="xs:string*" select="'1', '2', '3'"/>
<xsl:variable name="vTest2" as="xs:string*" select="'1', '2', '3', '4'"/>
<xsl:template match="/">
<xsl:sequence select="not($vTest1[not(. = $vPermitted)])"/>
<xsl:sequence select="not($vTest2[not(. = $vPermitted)])"/>
</xsl:template>
</xsl:stylesheet>
当上述转换应用于任何 XML 文档(未使用)时,将评估两个 XPath 表达式并输出它们正确的、想要的结果:
true false
注意:
即使在没有序列概念的 XPath 1.0 (XSLT 1.0) 中也可以使用完全相同的表达式,但可以使用节点集代替。
解释:
这是“Principle of Double Negation”。这个原理被认为是经典逻辑中的一个思维规律。罗素和怀特海在《数学原理》中将该原理表述为命题逻辑定理:
"This is the principle of double negation, i.e. a proposition is equivalent of the falsehood of its negation."
最佳实施 -- 接近 O(N)
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:variable name="vPermitted" as="map(xs:string, xs:boolean)" select=
"map{'1' : true(), '2' : true(), '3' : true(), '278' : true()}"/>
<xsl:variable name="vTest1" as="xs:string*" select="'1', '2', '3'"/>
<xsl:variable name="vTest2" as="xs:string*" select="'1', '2', '3', '4'"/>
<xsl:template match="/">
<xsl:sequence select="not($vTest1[not($vPermitted(.))])"/>
<xsl:sequence select="not($vTest2[not($vPermitted(.))])"/>
</xsl:template>
</xsl:stylesheet>
当上述转换应用于任何 XML 文档(未使用)时,将评估两个 XPath 表达式并输出它们正确的、想要的结果:
true false
虽然前面的表达式(包括当前接受的答案中的表达式)都有时间复杂度O(M*N)
,但上面的XPath 3.1 expression uses a pre-populated (global / created only once) map所以任何检查如果一个键存在需要常数时间——因此这个算法的总时间复杂度是O(N)
这里我们做出合理的假设,即正在使用的 XPath 引擎具有经过良好优化的地图实现,例如基于哈希表的地图实现
集合操作不适用于字符串,但序列操作可以。您的尝试:
<xsl:if test="count($permitted | $test)=count($permitted)">
可以重写为:
<xsl:if test="deep-equal(distinct-values(($permitted, $test)), $permitted)">