简体   繁体   English

XQuery:如何知道是否有双峰?

[英]XQuery: How to know if there are doublets?

I have XML file there is <a> and <b> for each element我有 XML 文件,每个element都有<a><b>

I want to write a query using XQuery to return True or False我想使用 XQuery 编写查询以返回 True 或 False

there is an element called <element> .有一个名为<element>的元素。

each <element> has 2 element in it <a> and <b> .每个<element>中都有 2 个元素<a><b>

Return False: if there is any <a> has the same value as another <a> in another element && there <b> 's value are different返回 False:如果有任何<a>与另一个元素中的另一个<a>具有相同的值 && 则<b>的值不同

otherwise True: <a> values are differnt in each element or there is similarity but there <b> values are different否则为真:每个元素中的<a>值不同或存在相似性但<b>值不同

for example例如

<root>
<element>
   <a>ttt</a>
   <b>tttsame</b>
</element>
<element>
   <a>ttt</a>
   <b>tttsame</b>
</element>
<element>
   <a/>
   <b>value</b>
</element>
<element>
   <a>rrr</a>
   <b>rrrvalue</b>
</element>
<element>
   <a>mmm</a>
   <b>rrrvalue</b>
</element>
<element>
   <a>mmm</a>
   <b>rrrvalue</b>
</element>
</root>

This one should be okay should return true这个应该没问题应该返回true

<root>
<element>
   <a>ttt</a>
   <b>ttt value</b>
</element>
<element>
   <a>ttt</a>
   <b>ttrdiff</b>
</element>
<element>
   <a/>
   <b>value</b>
</element>
<element>
   <a>mmm</a>
   <b>rrrvalue</b>
</element> 
</root>

shoudn't be accepted because ttt has two different values should return false不应该被接受,因为 ttt 有两个不同的值应该返回 false

You could group on a and then check if there is more than one distinct b in any group, for instance with您可以对a进行分组,然后检查任何组中是否有多个不同的b ,例如

not
(
    for $a-group in root/element
    group by $a := $a-group/a
    where tail(distinct-values($a-group/b))
    return $a-group
)

https://xqueryfiddle.liberty-development.net/6qM2e2r/0 and https://xqueryfiddle.liberty-development.net/6qM2e2r/1 has your two input samples. https://xqueryfiddle.liberty-development.net/6qM2e2r/0https://xqueryfiddle.liberty-development.net/6qM2e2r/1有两个输入样本。

As for how it works, the question asks to return false "if there is any <a> has the same value as another <a> in another element && there <b> 's value are different".至于它是如何工作的,问题要求返回 false “如果有任何<a>与另一个元素中的另一个<a>具有相同的值 && 那里<b>的值不同”。

To find element elements with the same a child element we can group by $a:= $a-group/a in a for $a-group in root/element expression.要查找具有相同子元素a element元素,我们可以group by $a:= $a-group/a in a for $a-group in root/element表达式进行分组。 The distinct or different b values in each group of a s with the same value are computed by distinct-values($a-group/b) , if there are at least two different b values then tail(distinct-values($a-group/b)) contains at least one value, otherwise it is an empty sequence.每组a中具有相同值的不同或不同b值由distinct-values($a-group/b)计算,如果至少有两个不同的b值,则tail(distinct-values($a-group/b))至少包含一个值,否则为空序列。 This works as through XQuery 3's group by clause "In the post-grouping tuple generated for a given group, each non-grouping variable is bound to a sequence containing the concatenated values of that variable in all the pre-grouping tuples that were assigned to that group" ( https://www.w3.org/TR/xquery-31/#id-group-by ) so that after the group by $a:= $a-group/a clause the variable $a-group is bound to a sequence of element elements with the same grouping key based on the a child element.这就像通过 XQuery 3 的group by子句“在为给定组生成的分组后元组中,每个非分组变量都绑定到一个序列,该序列包含分配给的所有预分组元组中该变量的连接值该组”( https://www.w3.org/TR/xquery-31/#id-group-by )以便在group by $a:= $a-group/a子句之后变量$a-group a子元素绑定到具有相同分组键的element元素序列。

So the complete for.. group by.. where.. return selects the groups of element elements with the same a value where there are at least two different/distinct b values.因此,完整for.. group by.. where.. return选择具有相同a值的element元素组,其中至少有两个不同/不同的b值。

As the requirement is to "return false" if any such groups exist the not() function is applied to implement that condition as the boolean value of a non-empty sequence is true and the not(..) then gives false if there are any elements meeting the condition expressed in the for selection.如果存在任何此类组,则要求“返回 false”,因此not() function 应用于实现该条件,因为非空序列的 boolean 值为 true,如果存在则not(..)给出 false for选择中表达的条件的任何元素。

Simple XPath 2.0 :简单 XPath 2.0

empty(
        (for $parentA-Dubled in /*/*[a = following-sibling::*/a]
           return
             empty($parentA-Dubled/following-sibling::*
                                        [$parentA-Dubled/a eq a and $parentA-Dubled/b ne b])
        )
        [not(.)]
      )

XSLT 2.0 - based verification: XSLT 2.0 - 基于验证:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

  <xsl:template match="/">
    <xsl:value-of select=
    "empty(
            (for $parentA-Dubled in /*/*[a = following-sibling::*/a]
              return
                empty($parentA-Dubled/following-sibling::*
                                         [$parentA-Dubled/a eq a and $parentA-Dubled/b ne b])
            )
             [not(.)]
          )
     "/>
    </xsl:template>
</xsl:stylesheet>

When this transformation is applied on any XML document, it evaluates the XPath expression and outputs the result of this evaluation .当此转换应用于任何 XML 文档时,它会评估 XPath 表达式并输出此评估的结果

When applied on the first provided XML document, the wanted, correct result is produced:当应用于第一个提供的 XML 文档时,会产生所需的正确结果:

true

When applied on the second provided XML document, again the wanted, correct result is produced:当应用于第二个提供的 XML 文档时,再次产生所需的正确结果:

false

Explanation :说明

This sub-expression:这个子表达式:

(for $parentA-Dubled in /*/*[a = following-sibling::*/a]
               return
                 empty($parentA-Dubled/following-sibling::*
                          [$parentA-Dubled/a eq a and $parentA-Dubled/b ne b])

evaluates to a sequence of boolean values: true() / false()评估为 boolean 值序列: true() / false()

true() is returned when this is true:如果为真,则返回true()

empty($parentA-Dubled/following-sibling::*
                          [$parentA-Dubled/a eq a and $parentA-Dubled/b ne b])

This means that true() is returned for every occasion when there is an $parentA-Dubled/a that has no other a (a child of a following sibling of $parentA-Dubled with the same value as $parentA-Dubled/a but the value of its b sibling is different than the value of $parentA-Dubled/b .这意味着当$parentA-Dubled/a没有其他a true() $parentA-Dubled的下一个兄弟的孩子与$parentA-Dubled/a具有相同的值但其b兄弟的值不同于$parentA-Dubled/b的值。

To summarize : true() is returned when for all a elements with the same value, their b siblings also have (all b s) the same value总结一下:对于所有具有相同值的a元素,当它们的b兄弟也具有(所有b s)相同的值时,返回true()

Then when is the case when false() is returned?那么什么时候返回false()呢?

Returning false() means that empty() returned false() -- that is, there exists at least one occasion of two a elements that have the same value, but their b siblings have different values.返回false()意味着empty()返回false() ——也就是说,至少存在一次两个a元素具有相同的值,但它们的b兄弟元素具有不同的值。

Thus, the sub-expression above returns a sequence such as:因此,上面的子表达式返回一个序列,例如:

true(), true(), true(), ..., true() -- all values are true() true(), true(), true(), ..., true() -- 所有值都是true()

or或者

true(), true(), true(), ..., false), ..., true() -- at least one of the values is false() true(), true(), true(), ..., false), ..., true() -- 至少其中一个值为false()

The original problem requires us to return true() in the first case and to return false() in the second case.最初的问题要求我们在第一种情况下返回true() false() ,在第二种情况下返回 false()。

This is easy to express as:这很容易表达为:

empty($booleanSequence[. eq false()]) -- and this is equivalent to the shorter: empty($booleanSequence[. eq false()]) - 这相当于较短的:

empty($booleanSequence[not(.)])

Now, we just need to substitute in the above expression $booleanSequence with the first sub-expression that we analyzed above:现在,我们只需将上面的表达式$booleanSequence替换为我们上面分析的第一个子表达式:

(for $parentA-Dubled in /*/*[a = following-sibling::*/a]
               return
                 empty($parentA-Dubled/following-sibling::*
                          [$parentA-Dubled/a eq a and $parentA-Dubled/b ne b])

Thus we obtain the complete XPath expression that solves the original problem:这样我们就得到了解决原问题的完整 XPath 表达式:

empty(
        (for $parentA-Dubled in /*/*[a = following-sibling::*/a]
           return
             empty($parentA-Dubled/following-sibling::*
                                        [$parentA-Dubled/a eq a and $parentA-Dubled/b ne b])
        )
        [not(.)]
      )

Try this XQuery code to get only one distinct item of <a> (The corresponding <b> value is not specified; here, the first element is chosen):试试这个 XQuery 代码,只获取一个不同的<a>项(未指定相应的<b>值;这里选择了第一个元素):

let $file := doc("input.xml")/root,
    $vals := distinct-values($file/element/a) return
  <root>
    {for $i in $vals return $file/element[a=$i][1]}
  </root>

Its result is:其结果是:

<root>
    <element>
        <a>ttt</a>
        <b>ttt value</b>
    </element>
    <element>
        <a/>
        <b>value</b>
    </element>
    <element>
        <a>rrr</a>
        <b>rrrvalue</b>
    </element>
    <element>
        <a>mmm</a>
        <b>rrrvalue</b>
    </element>
</root>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM