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

时间:2015-05-11 10:46:57

标签: xquery exist-db

我认为,这可以使用分组来解决,但作为XQuery的初学者,我无法编写有效的查询。 我正在使用带有XQuery version 3.

的eXist-db

我有两个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>

重点是最后三个记录(‘RACEx’)。

第二个文档具有以下记录(具有唯一记录,每个记录具有不同的USUBJID)。

<ItemGroupData ItemGroupOID="DM" data:ItemGroupDataSeq="1" >
<ItemData ItemOID="DM.USUBJID" Value="01-701-1015"/>
<ItemData ItemOID="DM.RACE" Value="Multiple"/>
</ItemGroupData>
<ItemGroupData ItemGroupOID="DM" data:ItemGroupDataSeq="2" >
<ItemData ItemOID="DM.USUBJID" Value="01-701-1023"/>
<ItemData ItemOID="DM.RACE" Value="Multiple"/>
</ItemGroupData>

正如您所看到的,SUPPDM有多条记录具有相同的USUBJID,但可以有多个QNAM值。 我想检查QNAMUSUBJID对于某个RACEx是否为“DM.RACE is Multiple”。

我试着写一个XQuery,它实际上有点工作但是回报不知何故没有返回RACE的值..你能帮我吗?

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

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>

我不确定WHERE表达式。不幸的是,我的输出看起来像这样: &#34;数据集QNAM中的suppdm.xml值无效。 =&GT;&#34; $qnamvalue ...这总是空的。

(2015年12月5日更新) 在这里,我根据adamretter的建议发布了新的XQuery!

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>

我完全理解这些表达式,但是如何在QNAM中检索正确的RACE值呢?查询不按我想要的方式工作,不知怎的,我从DM返回所有记录。

至少,我得到multiple-usubjid的值(False或True),但我希望收到QNAM中包含USUBJID的{​​{1}}值。
我是一个真正的初学者,我不太清楚我必须在其他表达中加入什么,或者我必须如何重新组织&#34;查询。

再次感谢您的帮助! 克里斯蒂安

1 个答案:

答案 0 :(得分:0)

您正在寻找两个文件之间的简单连接,尽管您也可以在没有连接的情况下进行连接。因为您确实有两个查询,并且只有在第一个查询匹配时才需要执行第二个查询。

为了简化您的问题,我将您的两个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,可以将其提取到函数中或重写为更高效,但希望它是讨论的良好起点。