如何使用翻滚 window 按内容对 XML 元素进行分组?
How to use tumbling window to group XML elements by content?
如何根据 [0-9]
与 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>
概念是每个 "person" 将有一个名称(无数字)和可能的附加数据。因此,希望阅读每一行,然后根据找到名称的位置进行分组。
代码:
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"。但是,仍然有一些匹配发生。
来自撒克逊邮件列表:
On Wed, Feb 19, 2020 at 10:31:37AM -0800, thufir scripsit:
I'll re-read the section on windowing; my impression was that it was more
for display or report purposes.
开窗是从数据流中提取块的方法。
您得到的实际上是一系列线条元素;你可以
识别 "name" 行,但您现在不知道它们有多远 are/how
任何特定的一对名称之间有很多数据。
Windows 让你说“我想要这个流的块以
名称行并继续(但不包括)下一个名称
行”。
Would you elaborate on what you mean by two steps, a bit more concretely?
您正在尝试获取一些输入 XML 并将其转换为不同的输出
XML.
如果这是纯粹的转换 -- 更改所有名为 FOO 的元素
到名为 BAZ 的元素——XQuery 不是最好的工具选择。在以下情况下使用 XSLT
你可以。它们在计算上是相同的,但语言有
不同的偏见和 XSLT 确实更自然地转换。
如果输出 XML 是输入的抽象表示
-- 道德上的某种报告 -- 抽象然后呈现它有很大帮助。
所以在你的情况下,你拥有的是一个包含隐式
名称和数据之间的关联。 (这是一连串的线条;唯一的
您知道这些数据线与该名称线对应的方式是位置。所以
隐式。)如果你把它变成名称之间的显式映射
和数据——例如通过创建一个映射变量,其中键是
名称行的内容(以某种方式处理了空格)和
每个键的条目是与该名称关联的数据行——
你已经完成了抽象部分。
然后您可以获取该地图并生成您想要的 XML 输出
它,这比尝试组合 "create new XML" 简单得多
和 "do the abstraction steps"。我发布的最后一件事有一个
将地图转换为元素的示例,但作为模式它只是
地图:钥匙($地图)! {.}{$map(.)}
(如果你有节点或序列,它会变得更复杂
条目,但仅此而已。)
这让事情更接近意义?
-- 格雷登
_______________________________________________ saxon-help 邮件列表存档于 http://saxon.markmail.org/
撒克逊帮助@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/saxon-help
如果您使用的是 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>
未经测试,可能需要更正或改编。
这 probably 非常接近:
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>
以下尝试使用 tumbling window
,它以不包含任何 ASCII 数字(person
的 name
)的任何 line
开头,后跟任何包含至少一个 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>
如何根据 [0-9]
与 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>
概念是每个 "person" 将有一个名称(无数字)和可能的附加数据。因此,希望阅读每一行,然后根据找到名称的位置进行分组。
代码:
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"。但是,仍然有一些匹配发生。
来自撒克逊邮件列表:
On Wed, Feb 19, 2020 at 10:31:37AM -0800, thufir scripsit:
I'll re-read the section on windowing; my impression was that it was more for display or report purposes.
开窗是从数据流中提取块的方法。
您得到的实际上是一系列线条元素;你可以 识别 "name" 行,但您现在不知道它们有多远 are/how 任何特定的一对名称之间有很多数据。
Windows 让你说“我想要这个流的块以 名称行并继续(但不包括)下一个名称 行”。
Would you elaborate on what you mean by two steps, a bit more concretely?
您正在尝试获取一些输入 XML 并将其转换为不同的输出 XML.
如果这是纯粹的转换 -- 更改所有名为 FOO 的元素 到名为 BAZ 的元素——XQuery 不是最好的工具选择。在以下情况下使用 XSLT 你可以。它们在计算上是相同的,但语言有 不同的偏见和 XSLT 确实更自然地转换。
如果输出 XML 是输入的抽象表示 -- 道德上的某种报告 -- 抽象然后呈现它有很大帮助。
所以在你的情况下,你拥有的是一个包含隐式 名称和数据之间的关联。 (这是一连串的线条;唯一的 您知道这些数据线与该名称线对应的方式是位置。所以 隐式。)如果你把它变成名称之间的显式映射 和数据——例如通过创建一个映射变量,其中键是 名称行的内容(以某种方式处理了空格)和 每个键的条目是与该名称关联的数据行—— 你已经完成了抽象部分。
然后您可以获取该地图并生成您想要的 XML 输出 它,这比尝试组合 "create new XML" 简单得多 和 "do the abstraction steps"。我发布的最后一件事有一个 将地图转换为元素的示例,但作为模式它只是
地图:钥匙($地图)! {.}{$map(.)}
(如果你有节点或序列,它会变得更复杂 条目,但仅此而已。)
这让事情更接近意义?
-- 格雷登
_______________________________________________ saxon-help 邮件列表存档于 http://saxon.markmail.org/ 撒克逊帮助@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/saxon-help
如果您使用的是 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>
未经测试,可能需要更正或改编。
这 probably 非常接近:
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>
以下尝试使用 tumbling window
,它以不包含任何 ASCII 数字(person
的 name
)的任何 line
开头,后跟任何包含至少一个 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>