[英]Finding element in XML database with certain attribute value in xQuery
我正面临以下问题陈述:
对于由两个或多个其他管理单位共同管理的每个管理单位,请验证:
该数据库如下所示:
<?xml version "1.0" ?>
<wfs:FeatureCollection xmlns:au="http://inspire.ec.europa.eu/schemas/au/4.0"
xmlns:gts="http://www.isotc211.org/2005/gts" xmlns:gco="http://www.isotc211.org/2005/gco"
xmlns:ns1="http://www.w3.org/1999/xhtml"
xmlns:hfp="http://www.w3.org/2001/XMLSchema-hasFacetAndProperty"
xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:gn="http://inspire.ec.europa.eu/schemas/gn/4.0"
xmlns:gss="http://www.isotc211.org/2005/gss" xmlns:gsr="http://www.isotc211.org/2005/gsr"
xmlns:base="http://inspire.ec.europa.eu/schemas/base/3.3"
xmlns:gmd="http://www.isotc211.org/2005/gmd" xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:wfs="http://www.opengis.net/wfs/2.0"
xsi:schemaLocation="http://inspire.ec.europa.eu/schemas/au/4.0 http://inspire.ec.europa.eu/schemas/au/4.0/AdministrativeUnits.xsd http://www.opengis.net/wfs/2.0 http://schemas.opengis.net/wfs/2.0/wfs.xsd"
numberMatched="274" numberReturned="274" timeStamp="2016-03-29T18:12:51.630+02:00">
<wfs:member>
<au:AdministrativeUnit gml:id="NC.MT01402">
<au:administeredBy xlink:href="#NC.MT01310"/>
<au:administeredBy xlink:href="#NC.MT01407"/>
<au:coAdminister nilReason="Unpopulated"/>
</au:AdministrativeUnit>
</wfs:member>
<wfs:member>
<au:AdministrativeUnit gml:id="NC.MT01310">
<au:administeredBy nilReason="Unpopulated" xsi:nil="true"/>
<au:coAdminister xlink:href="#NC.MT01402"/>
</au:AdministrativeUnit>
</wfs:member>
<wfs:member>
<au:AdministrativeUnit gml:id="NC.MT01407">
<au:upperLevelUnit xlink:href="#NC.MT0xxxx"/>
<au:administeredBy nilReason="Unpopulated" xsi:nil="true"/>
<au:coAdminister xlink:href="#NC.MT01402"/>
</au:AdministrativeUnit>
</wfs:member>
</wfs:FeatureCollection>
我编写了以下xQuery表达式:
let $administrativeUnits := $features[self::*:AdministrativeUnit]
let $featuresWithErrors :=
(for $candidate in $administrativeUnits
let $administeredBy := $candidate/au:administeredBy/@xlink:href
let $candidateVal := string($candidate/@gml:id)
return
if (count($administeredBy) >= 2) then (
let $coAdminCheck :=
(for $administer in $administeredBy
let $administerVal := string($administer)
let $coAdminVal := $administrativeUnits/au:AdministrativeUnit[@gml:id = $administerVal]/au:coAdminister/@xlink:href
return
if (string($coAdminVal) = $candidateVal) then () else $administer
)
return
if ($coAdminCheck) then $candidate else ()
)
else ()
)[position() le $limitErrors]
return
(if ($featuresWithErrors) then 'FAILED' else 'PASSED',
local:error-statistics('TR.featuresWithErrors', count($featuresWithErrors)),
for $feature in $featuresWithErrors
order by $feature/@gml:id
return local:addMessage('TR.noCoAdministered', map { 'filename': local:filename($feature), 'featureType': local-name($feature), 'gmlid': string($feature/@gml:id), 'adminBy' : string($feature/au:administeredBy[1]/@xlink:href) }))
但是,即使不是这样,我也总是得到“失败”的结果。
我相信问题出在以下陈述中:
let $coAdminVal := $administrativeUnits/au:AdministrativeUnit[@gml:id = $administerVal]/au:coAdminister/@xlink:href
因为$ coAdminVal似乎总是空的。
我尝试了几种其他方式来编写此语句,但事实证明都是错误的:
let $coAdminVal := $administrativeUnits/au:AdministrativeUnit[matches(@gml:id, $administerVal)]/au:coAdminister/@xlink:href
let $coAdminVal := $administrativeUnits/au:AdministrativeUnit[contains(@gml:id, $administerVal)]/au:coAdminister/@xlink:href
let $coAdminVal := $administrativeUnits/au:AdministrativeUnit[string(@gml:id) = $administerVal]/au:coAdminister/@xlink:href
正确的方法是什么?
我同意,看来问题出在谓词的比较表达式中:
[@gml:id = $administerVal]
由于$administerVal
本质上是au:administeredBy/@xlink:href
属性,因此让我们看一下要比较的内容:
gml:id="NC.MT01402"
xlink:href="#NC.MT01310"
xlink:href="#NC.MT01407"
区别在于@xlink:href
值前面带有#
号。 为了解决这个问题,请将您的比较更改为:
[@gml:id = substring-after($administerVal, "#")]
您使用contains()
其他方法失败,因为您正在询问是否类似NC.MT01402
的值包含#NC.MT01402
。 反转参数即可。
同样适用于matches()
-尽管请注意,此函数采用正则表达式模式,所以像这样的字符.
可以匹配任何字符,而不仅仅是文字字符。 要强制搜索立即数字符,您需要对其进行转义,例如matches("#NC.MT01402", "NC\\.MT01402")
。
考虑到matches()
的额外复杂性(除非您真的想要模式匹配而不是文字比较),我想说用substring()
或使用contains()
修剪$administerVal
是最好的方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.