带有子串的字符串上的XQuery

时间:2015-03-25 01:20:04

标签: xml xquery tokenize basex

以下是我使用的数据库中的代码示例:

<mondial>
<mountain id="mount-Sajama" country="BOL" type="volcano">
<name>Sajama</name>
<mountains>Andes</mountains>
<located country="BOL" province="prov-BOL-2"/>
<elevation>6542</elevation>
<longitude>-68.9</longitude>
<latitude>-18.1</latitude>
</mountain>
<mountain id="mount-Licancabur" country="BOL RCH" type="volcano">
<name>Licancabur</name>
<mountains>Andes</mountains>
<located country="BOL" province="prov-BOL-3"/>
<located country="RCH" province="prov-Chile-2"/>
<elevation>5920</elevation>
<longitude>-67.9</longitude>
<latitude>-22.8</latitude>
</mountain>
<country car_code="N" area="324220" capital="cty-Norway-Oslo" memberships="org-AfDB org-AsDB org-BIS org-CE org-CBSS org-CCC org-ECE org-EBRD org-EFTA org-CERN org-ESA org-FAO org-IADB org-IAEA org-IBRD org-ICC org-ICAO org-ICFTU org-Interpol org-IDA org-IEA org-IFRCS org-IFC org-IFAD org-ILO org-IMO org-Inmarsat org-IMF org-IOC org-IOM org-ISO org-ICRM org-ITU org-Intelsat org-MTCR org-NAM org-NC org-NIB org-ANC org-NATO org-EN org-NSG org-OECD org-OSCE org-PCA org-UN org-UNAVEM-III org-UNCRO org-UNESCO org-UNIDO org-UNITAR org-UNIFIL org-MINURSO org-UNHCR org-UNPREDEP org-UNPROFOR org-UNTSO org-UPU org-WEU org-WHO org-WIPO org-WMO org-WTrO org-ZC">
<name>Norway</name>
<population>4383807</population>
<population_growth>0.48</population_growth>
<infant_mortality>4.9</infant_mortality>
<gdp_total>106200</gdp_total>
<gdp_agri>2.9</gdp_agri>
<gdp_ind>34.7</gdp_ind>
<gdp_serv>62.4</gdp_serv>
<inflation>2.5</inflation>
<indep_date from="S">1905-10-26</indep_date>
<government>constitutional monarchy</government>
<encompassed continent="europe" percentage="100"/>
<ethnicgroup percentage="82.5">Norwegian</ethnicgroup>
<ethnicgroup percentage="1.5">Sami</ethnicgroup>
<religion percentage="86.7">Protestant</religion>
<religion percentage="1">Roman Catholic</religion>
<religion percentage="1.8">Muslim</religion>
<language percentage="99">Norwegian</language>
<border country="R" length="167"/>
<border country="SF" length="729"/>
<border country="S" length="1619"/>
<province id="lteil-OS-N" capital="cty-Norway-Oslo" country="N">
<name>Oslo</name>
<population>449337</population>
<city id="cty-Norway-Oslo" is_country_cap="yes" is_state_cap="yes" country="N" province="lteil-OS-N">
<name>Oslo</name>
<longitude>10.7333</longitude>
<latitude>59.9333</latitude>
<population year="87">449337</population>
<located_at watertype="sea" sea="sea-Skagerrak"/>
</city>
</province>
<province id="lteil-AK-N" capital="cty-Norway-Oslo" country="N">
<name>Akershus</name>
<population>393217</population>
</province>
</mondial>

您可以在此处找到完整的XML文件: https://www.kth.se/social/files/54f4817bf27654358032133f/mondial.xml

我遇到了一些问题,因为在我的数据库中存在国家代码(山区的国家和国家/地区的car_codes),其中多个国家/地区可以使用相同的国家/地区代码编写,因为您可以看到一个示例挂载利坎卡武尔火山。

所以现在我想为每个大陆选择最高的山峰,所以我写了下面的代码:

let $mondial := db:open('mondial')
for $country in $mondial/mondial/country/encompassed/@continent
for $mountains in $mondial/mondial/mountain
where contains($country/../../@car_code, $mountains/@country)

(: Tokenize ev för att lösa berg i två länder :)
let $elevation := $mountains/elevation
group by $country

return ($country, max($elevation))

这给出了输出:

europe
5642
asia
8167
africa
5895
australia
5775
america
6962

这些看起来似乎是正确的,但珠穆朗玛峰应该是亚洲最大的山峰,高度为8848米。

所以我的问题是你,我怎么能比较car_code / country中有两个国家代码的国家代码?我一直在阅读有关令牌化的内容,但到目前为止还没有能够使其发挥作用。

希望有人可以帮助我,一直坚持这一点:)

1 个答案:

答案 0 :(得分:1)

从阅读你的问题并查看xml看起来你正试图解决看起来像这样的mount元素的问题:

<mountain id="mount-Matterhorn" country="CH I">
 <name>Matterhorn</name>
 <mountains>Alps</mountains>
 <located country="CH" province="prov-Switzerland-24"/>
 <located country="I" province="prov-Italy-9"/>
 <elevation>4478</elevation>
 <longitude>7.56</longitude>
 <latitude>46</latitude>
</mountain>

@country中有多个国家/地区。

你可以通过改变这个

的位置来实现这一点
where $mountains[tokenize(@country, " ") eq $country/../../@car_code]

您在这里做的事情存在一些性能问题。每个山区元素都将为每个国家标记。这可以写得更高效,如果你愿意,我可以和你一起讨论。

更新:

这是另一种方法,它将为您提供每个大陆的最高海拔。通过XML的方式,你必须在山上使用tokenize来比较各县,但至少这样它只对每个大陆的每座山都有。

for $continent in fn:distinct-values($mondial/mondial/country/encompassed/@continent)
let $counties := $mondial/mondial/country[encompassed/@continent eq $continent]/@car_code
let $highest :=
(
    for $elevation in $mondial/mondial/mountain[fn:tokenize(@country, " ") = $counties]/elevation/text()
    order by xs:int($elevation) descending
    return $elevation
)[1]
return ($continent, $highest)

输出

europe
7010
asia
8848
africa
5895
australia
4884
america
6962