XQuery v3-比较两个不同文件的两个值

XQuery v3-比较两个不同文件的两个值,xquery,exist-db,Xquery,Exist Db,我想,这可以通过分组来解决,但作为XQuery的初学者,我不太能够编写功能强大的查询。 我使用的是eXist db,带有XQuery版本3。 我有两个XML文档。第一个包含如下所示的记录: <ItemGroupData ItemGroupOID="SUPPDM" data:ItemGroupDataSeq="1" > <ItemData ItemOID="SUPPDM.USUBJID" Value="01-701-1015"/> <ItemData ItemOID=

我想,这可以通过分组来解决,但作为XQuery的初学者,我不太能够编写功能强大的查询。 我使用的是eXist db,带有
XQuery版本3。

我有两个XML文档。第一个包含如下所示的记录:

<ItemGroupData ItemGroupOID="SUPPDM" data:ItemGroupDataSeq="1" >
<ItemData ItemOID="SUPPDM.USUBJID" Value="01-701-1015"/>
<ItemData ItemOID="SUPPDM.QNAM" Value="COMPLT16"/>
<ItemData ItemOID="SUPPDM.QLABEL" Value="Completers of Week 16 Population Flag"/>
</ItemGroupData>
<ItemGroupData ItemGroupOID="SUPPDM" data:ItemGroupDataSeq="2" >
<ItemData ItemOID="SUPPDM.USUBJID" Value="01-701-1015"/>
<ItemData ItemOID="SUPPDM.QNAM" Value="COMPLT24"/>
<ItemData ItemOID="SUPPDM.QLABEL" Value="Completers of Week 24 Population Flag"/>
</ItemGroupData>
<ItemGroupData ItemGroupOID="SUPPDM" data:ItemGroupDataSeq="3" >
<ItemData ItemOID="SUPPDM.USUBJID" Value="01-701-1015"/>
<ItemData ItemOID="SUPPDM.QNAM" Value="COMPLT8"/>
<ItemData ItemOID="SUPPDM.QLABEL" Value="Completers of Week 8 Population Flag"/>
</ItemGroupData>
<ItemGroupData ItemGroupOID="SUPPDM" data:ItemGroupDataSeq="4" >
<ItemData ItemOID="SUPPDM.USUBJID" Value="01-701-1015"/>
<ItemData ItemOID="SUPPDM.QNAM" Value="EFFICACY"/>
</ItemGroupData>
<ItemGroupData ItemGroupOID="SUPPDM" data:ItemGroupDataSeq="5" >
<ItemData ItemOID="SUPPDM.USUBJID" Value="01-701-1015"/>
<ItemData ItemOID="SUPPDM.QNAM" Value="ITT"/>
<ItemData ItemOID="SUPPDM.QLABEL" Value="Intent to Treat Population Flag"/>
</ItemGroupData>
<ItemGroupData ItemGroupOID="SUPPDM" data:ItemGroupDataSeq="6" >
<ItemData ItemOID="SUPPDM.USUBJID" Value="01-701-1015"/>
<ItemData ItemOID="SUPPDM.QNAM" Value="SAFETY"/>
<ItemData ItemOID="SUPPDM.QLABEL" Value="Safety Population Flag"/>
</ItemGroupData>
<ItemGroupData ItemGroupOID="SUPPDM" data:ItemGroupDataSeq="7" >
<ItemData ItemOID="SUPPDM.USUBJID" Value="01-701-1023"/>
<ItemData ItemOID="SUPPDM.QNAM" Value="EFFICACY"/>
<ItemData ItemOID="SUPPDM.QLABEL" Value="Efficacy Population Flag"/>
</ItemGroupData>
<ItemGroupData ItemGroupOID="SUPPDM" data:ItemGroupDataSeq="8" >
<ItemData ItemOID="SUPPDM.USUBJID" Value="01-701-1023"/>
<ItemData ItemOID="SUPPDM.QNAM" Value="ITT"/>
<ItemData ItemOID="SUPPDM.QLABEL" Value="Intent to Treat Population Flag"/>
</ItemGroupData>
<ItemGroupData ItemGroupOID="SUPPDM" data:ItemGroupDataSeq="9" >
<ItemData ItemOID="SUPPDM.USUBJID" Value="01-701-1023"/>
<ItemData ItemOID="SUPPDM.QNAM" Value="SAFETY"/>
<ItemData ItemOID="SUPPDM.QLABEL" Value="Safety Population Flag"/>
</ItemGroupData>
<ItemGroupData ItemGroupOID="SUPPDM" data:ItemGroupDataSeq="1198" >
<ItemData ItemOID="SUPPDM.USUBJID" Value="01-701-1015"/>
<ItemData ItemOID="SUPPDM.QNAM" Value="RACE1"/>
</ItemGroupData>
<ItemGroupData ItemGroupOID="SUPPDM" data:ItemGroupDataSeq="1199" >
<ItemData ItemOID="SUPPDM.USUBJID" Value="01-701-1015"/>
<ItemData ItemOID="SUPPDM.QNAM" Value="RACE2"/>
</ItemGroupData>
<ItemGroupData ItemGroupOID="SUPPDM" data:ItemGroupDataSeq="1200" >
<ItemData ItemOID="SUPPDM.USUBJID" Value="01-701-1023"/>
<ItemData ItemOID="SUPPDM.QNAM" Value="RACE1"/>
</ItemGroupData>
如您所见,
SUPPDM
有多个记录具有相同的
USUBJID
,但可以有多个
QNAM
值。 我想检查,当
DM.RACE是多个
时,某个
USUBJID
QNAM
是否为“
RACEx

我试着编写一个XQuery,它实际上可以正常工作,但是返回的值不一定返回
RACE
。。你能帮帮我吗

这是我的XQuery(在开始时,我声明了从另一个元数据XML文件获取的变量):

我完全理解这些表达式,但是如何在
RACE
中检索正确的
QNAM
值呢?查询没有按我所希望的方式工作,不知何故,我得到了从
DM
返回的所有记录

至少,我为
多个usubjid
获取了一个值(False或True),但我想为包含
种族的特定
usubjid
接收
QNAM
值。
我是一个真正的初学者,我不太知道我必须在else表达式中输入什么,或者我必须如何“重新组织”查询

再次感谢你的帮助!
Christiane

您正在寻找跨这两个文件的简单联接,尽管您也可以不进行联接。因为您确实有两个查询,只有在第一个查询匹配时才需要执行第二个查询

为了简化您的问题,我将您的两个XML文件存储到
/tmp/doc1.XML
/tmp/doc2.XML
中,并将重点放在查找您感兴趣的节点上,上面的许多XQuery并没有真正关注您遇到的核心问题。无论如何,这是我提出的解决方案-

xquery version "1.0";

(: the USUBJID you are interested in :)
declare variable $local:usubjid := "01-701-1015";

let $multiple-usubjid :=
    not(empty(
        doc("/tmp/doc2.xml")
            //ItemGroupData[ItemData[@ItemOID eq "DM.USUBJID"]
               [@Value eq $local:usubjid]][ItemData[@ItemOID eq "DM.RACE"]
               [@Value eq "Multiple"]]
    ))
return
    if($multiple-usubjid) then
        doc("/tmp/doc1.xml")
            //ItemGroupData[ItemData[@ItemOID eq "SUPPDM.USUBJID"]
               [@Value eq $local:usubjid]][ItemData[@ItemOID eq "SUPPDM.QNAM"]
               [fn:matches(@Value, "RACE[0-9]+")]]
    else()

现在很明显,如果你想测试所有的
USUBJID
,这可以被提取到函数中,或者重写为更有效,但希望这是一个讨论的好起点。

Hey@adamretter,谢谢你的帮助,这是一个很好的起点,而且我似乎离解决方案越来越近了!我更新了我的问题并使用了你的解决方案,但它还没有按照我预期的方式工作。我使用非局部变量,因为我在DM中有300条记录,所以我尝试使用泛型。
xquery version "3.0";
declare namespace def = "http://www.cdisc.org/ns/def/v2.0";
declare namespace odm="http://www.cdisc.org/ns/odm/v1.3";
declare namespace data="http://www.cdisc.org/ns/Dataset-XML/v1.0";
declare namespace xlink="http://www.w3.org/1999/xlink";

let $base := '/db/mydataset/'
let $define := 'define_2_0.xml'

(: get the SUPPDM dataset :)
let $suppdmdataset := doc(concat($base,$define))//odm:ItemGroupDef[@Name='SUPPDM']
let $suppdmdatasetname := $suppdmdataset/def:leaf/@xlink:href
let $suppdmdatasetlocation := concat($base,$suppdmdatasetname)

(: get the DM dataset :)
let $dmdataset := doc(concat($base,$define))//odm:ItemGroupDef[@Name='DM']
let $dmdatasetname := $dmdataset/def:leaf/@xlink:href
let $dmdatasetlocation := concat($base,$dmdatasetname)

(:get the USUBJID in DM :)
let $dmusubjidoid := (
    for $a in doc(concat($base,$define))//odm:ItemDef[@Name='USUBJID']/@OID 
    where $a = doc(concat($base,$define))//odm:ItemGroupDef[@Name='DM']/odm:ItemRef/@ItemOID
    return $a
)
(:get the USUBJID in SUPPDM :)
let $suppdmusubjidoid := (
    for $a in doc(concat($base,$define))//odm:ItemDef[@Name='USUBJID']/@OID 
    where $a = doc(concat($base,$define))//odm:ItemGroupDef[@Name='SUPPDM']/odm:ItemRef/@ItemOID
    return $a
)
(: get the OID of RACE in DM dataset :)
let $raceoid := (
    for $a in doc(concat($base,$define))//odm:ItemDef[@Name='RACE']/@OID 
    where $a = doc(concat($base,$define))//odm:ItemGroupDef[@Name='DM']/odm:ItemRef/@ItemOID
    return $a
)
(: get the OID of QNAM in SUPPDM :)
let $qnamoid := (
    for $a in doc(concat($base,$define))//odm:ItemDef[@Name='QNAM']/@OID 
    where $a = doc(concat($base,$define))//odm:ItemGroupDef[@Name='SUPPDM']/odm:ItemRef/@ItemOID
    return $a
)
(:substring(QNAM,1,4) = „RACE“ :)

(:we are searching through the subjects in DM that have the value "Multiple" in RACE :)

for $record in doc($dmdatasetlocation)//odm:ItemGroupData[odm:ItemData[@ItemOID=$raceoid and upper-case(@Value)='MULTIPLE']]
(:or for $record in doc($suppdmdatasetlocation)//odm:ItemGroupData[odm:ItemData[@ItemOID=$qnamoid]]/starts-with(@Value,"RACE") :)

    let $recnum := $record/@data:ItemGroupDataSeq

(: Get the DM USUBJID value :)
let $dmusubjidvalue := $record/odm:ItemData[@ItemOID=$dmusubjidoid]/@Value

(: now get the value of QNAM in SUPPDM for the subject with the corresponding USUBJID - it should be "RACE1", RACE2 or ... "RACEn"; principally it should start with 'RACE' :)
let $qnamvalue := (
    for $a in doc($suppdmdatasetlocation)//odm:ItemGroupData[odm:ItemData[@ItemOID=$suppdmusubjidoid and @Value=$dmusubjidvalue]]
    let $b := doc($suppdmdatasetlocation)//odm:ItemGroupData[odm:ItemData[@ItemOID=$qnamoid]]/upper-case(@Value)
    where (starts-with($b, 'RACE'))
    return $a
)

(:now check, whether the value QNAM starts with 'RACE' :)

(:  where not(starts-with($qnamvalue, "RACE")):)

    return <warning recordnumber="{data($recnum)}">Invalid value for QNAM in dataset {data($suppdmdatasetname)} - Label={data($qnamvalue)}. => RACE in {data($dmdatasetlocation)} for subject {data($dmusubjidvalue)} is 'Multiple', so QNAM should be in (RACE1, RACE2,... RACEn). If RACE is 'Multiple', additional information has to be added to the Supplemental Qualifier dataset of DM  (SUPPDM)       </warning>
for $record in doc($dmdatasetlocation)//odm:ItemGroupData
let $recnum := $record/@data:ItemGroupDataSeq

(: get value of usubjid :)
let $dmusubjidvalue := $record//odm:ItemData[@ItemOID=$dmusubjidoid]/@Value

(:check, whether this usubjid has a record in SUPPDM that has QNAM in 'RACEx' :)
let $multiple-usubjid :=
    not(empty(doc("$dmdatasetlocation")//odm:ItemGroupData[odm:ItemData[@ItemOID =$dmusubjidoid][@Value =$dmusubjidvalue]][odm:ItemData[@ItemOID eq $raceoid][@Value eq "Multiple"]]
    ))
return
(:it will return give a return if there exists a usubjid that has a QNAM that matches RACE :)
    if($multiple-usubjid) then
        doc($suppdmdatasetlocation)//odm:ItemGroupData[odm:ItemData[@ItemOID = $suppdmusubjidoid][@Value = $dmusubjidvalue]][odm:ItemData[@ItemOID =$qnamoid]
               [fn:matches(@Value, "RACE[0-9]+")]]
        else( 
 <warning rule="SPC_DM_RACE_01" rulelastupdate="2015-02-10" recordnumber="{data($recnum)}">Invalid value for QNAM in dataset {data($suppdmdatasetname)} - Label={data($multiple-usubjid)}. => RACE in {data

($dmdatasetlocation)} for subject {data($dmusubjidvalue)} is 'Multiple', so QNAM should be in (RACE1, RACE2,... RACEn). If RACE is 'Multiple', additional information has to be added to the Supplemental Qualifier dataset of DM  (SUPPDM)       

</warning>
xquery version "1.0";

(: the USUBJID you are interested in :)
declare variable $local:usubjid := "01-701-1015";

let $multiple-usubjid :=
    not(empty(
        doc("/tmp/doc2.xml")
            //ItemGroupData[ItemData[@ItemOID eq "DM.USUBJID"]
               [@Value eq $local:usubjid]][ItemData[@ItemOID eq "DM.RACE"]
               [@Value eq "Multiple"]]
    ))
return
    if($multiple-usubjid) then
        doc("/tmp/doc1.xml")
            //ItemGroupData[ItemData[@ItemOID eq "SUPPDM.USUBJID"]
               [@Value eq $local:usubjid]][ItemData[@ItemOID eq "SUPPDM.QNAM"]
               [fn:matches(@Value, "RACE[0-9]+")]]
    else()