0

如何根据是否匹配[0-9]带有 a 的数字进行分组tumbling window

所需的输出:

...
<record>
    <name>joe</name>
    <data>phone1</data>
    <data>phone2</data>
</record>
...

当前输出,未分组:

<xml>
  <record>
    <person key="$s" data="name">phone1</person>
  </record>
  <record>
    <person key="$s" data="name">phone2</person>
  </record>
  <record>
    <person key="$s" data="name">phone3sue</person>
  </record>
  <record>
    <person key="$s" data="name">cell4</person>
  </record>
  <record>
    <person key="$s" data="name">home5alice</person>
  </record>
  <record>
    <person key="$s" data="name">atrib6</person>
  </record>
  <record>
    <person key="$s" data="name">x7</person>
  </record>
  <record>
    <person key="$s" data="name">y9</person>
  </record>
  <record>
    <person key="$s" data="name">z10</person>
  </record>
</xml>

输入:

<text>
  <line>people</line>
  <line>joe</line>
  <line>phone1</line>
  <line>phone2</line>
  <line>phone3</line>
  <line>sue</line>
  <line>cell4</line>
  <line>home5</line>
  <line>alice</line>
  <line>atrib6</line>
  <line>x7</line>
  <line>y9</line>
  <line>z10</line>
</text>

这个概念是每个“人”都有一个名字(没有数字),也许还有其他数据。因此,希望阅读每一行,然后根据找到名称的位置进行分组。

代码:

xquery version "3.0";

<xml>
{
for tumbling window $line in db:open("foo.txt")//text()
start $s when matches($s, '[0-9]')
return   
<record>

       <person key='$s' data="name">{$line}</person>

 </record>
}
 </xml>

查看输出,“phone3sue”显然在进行一些匹配和分组,尽管并不完全符合预期,因为“phone3”应该在它自己的元素中,嵌套在“joe”而不是“sue”中。但是,仍然有一些匹配发生在那里。


来自撒克逊邮件列表:

2020 年 2 月 19 日星期三上午 10:31:37 -0800,thufir 脚本:

我将重新阅读有关窗口的部分;我的印象是它更多地用于显示或报告目的。

窗口化是您从数据流中取出块的方式。

您所拥有的是有效的线元素流;您可以识别“名称”行,但您现在不知道它们的距离/任何特定名称对之间的数据量。

Windows 让您说“我想要以名称行开头并继续(但不包括)下一个名称行的此流的块”。

您能否更具体地详细说明两个步骤的含义?

您正在尝试获取一些输入 XML 并将其转换为不同的输出 XML。

如果这是纯粹的转换——将所有名为 FOO 的元素更改为名为 BAZ 的元素——XQuery 不是最好的工具选择。如果可以,请使用 XSLT。它们在计算上是相同的,但语言有不同的偏见,XSLT 确实可以更自然地进行转换。

如果输出 XML 是您输入的抽象的表示——在道德上是某种报告——那么拥有抽象然后呈现它会有很大帮助。

因此,在您的情况下,您拥有的是一个包含名称和数据之间隐式关联的流。(这是一个行流;您知道这些数据行与该名称行一起使用的唯一方法是位置。所以隐含。)如果您将其转换为名称和数据之间的显式映射 - 例如通过创建一个映射变量,其中键是名称行的内容(以某种方式处理空格),每个键的条目是与该名称关联的数据行——您已经完成了抽象部分。

然后,您可以获取该映射并从中生成所需的 XML 输出,这比尝试结合“创建新 XML”和“执行抽象步骤”要简单得多。我发布的最后一件事是将地图转换为元素的示例,但作为一种模式,它只是

地图:钥匙($地图)!{.}{$map(.)}

(如果条目中有节点或序列,它会变得更加复杂,但不会更多。)

这让一些事情更接近意义?

——格雷登

_______________________________________________ saxon-help 邮件列表存档http://saxon.markmail.org/saxon-help@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/saxon-help

4

3 回答 3

1

如果您使用的是 3.0 或 3.1,则使用 FLWOR 表达式的“window”子句。就像是

for tumbling window $w in line
    start $s when matches($s, '[a-z]')
    return <group key="$s">{$w}</group>

未经测试,可能需要更正或调整。

于 2020-02-15T13:31:06.293 回答
1

以下尝试使用tumbling window以任何line不包含任何 ASCII 数字(的name)开头的 a person,后跟包含至少一个 ASCII 数字的任何行(即data行):

declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";

declare option output:method 'xml';
declare option output:indent 'yes';

<xml>
{
    for tumbling window $person in text/line
    start $name next $data when matches($name, '^[^0-9]+$') and matches($data, '[0-9]')
    return
        <person>
        {
            <name>{ data($name) }</name>,
            tail($person) ! <data>{data()}</data>

        }
        </person>
}    
</xml>

https://xqueryfiddle.liberty-development.net/gWmuPs1

输出有

<?xml version="1.0" encoding="UTF-8"?>
<xml>
   <person>
      <name>joe</name>
      <data>phone1</data>
      <data>phone2</data>
      <data>phone3</data>
   </person>
   <person>
      <name>sue</name>
      <data>cell4</data>
      <data>home5</data>
   </person>
   <person>
      <name>alice</name>
      <data>atrib6</data>
      <data>x7</data>
      <data>y9</data>
      <data>z10</data>
   </person>
</xml>
于 2020-02-20T07:33:45.553 回答
0

可能非常接近:

thufir@dur:~/flwor/foo.txt.database$ 
thufir@dur:~/flwor/foo.txt.database$ basex dennis.xq 
<person name="joe">
  <person id="3" x="0" numerical="true">phone1</person>
  <person id="4" x="0" numerical="true">phone2</person>
  <person id="5" x="0" numerical="true">phone3</person>
</person>
<person name="sue">
  <person id="7" x="0" numerical="true">cell4</person>
  <person id="8" x="0" numerical="true">home5</person>
</person>
<person name="alice">
  <person id="10" x="0" numerical="true">atrib6</person>
  <person id="11" x="0" numerical="true">x7</person>
  <person id="12" x="0" numerical="true">y9</person>
  <person id="13" x="0" numerical="true">z10</person>
</person>thufir@dur:~/flwor/foo.txt.database$ 

代码:

xquery version "3.0";

declare variable $XML := <xml>
 <person id="1" x="0" numerical="false">people</person>
 <person id="2" x="0" numerical="false">joe</person>
 <person id="3" x="0" numerical="true">phone1</person>
 <person id="4" x="0" numerical="true">phone2</person>
 <person id="5" x="0" numerical="true">phone3</person>
 <person id="6" x="0" numerical="false">sue</person>
 <person id="7" x="0" numerical="true">cell4</person>
 <person id="8" x="0" numerical="true">home5</person>
 <person id="9" x="0" numerical="false">alice</person>
 <person id="10" x="0" numerical="true">atrib6</person>
 <person id="11" x="0" numerical="true">x7</person>
 <person id="12" x="0" numerical="true">y9</person>
 <person id="13" x="0" numerical="true">z10</person>
</xml> ;

for $P in $XML/person
where $P[@numerical="true"]
let $PREV := $P/preceding-sibling::person[@numerical="false"][1]
group by $PREV
return <person name="{$PREV}" >  { $P } </person>
于 2020-02-20T06:49:52.717 回答