Permalänk
Medlem

XPath - predicates och AND

Hej, jag har XML-filer som innehåller block i stil med detta:

<species metaid="metaid_0000004" id="aspp" name="Aspartyl phosphate" compartment="compartment" initialConcentration="0"> <annotation> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:vCard="http://www.w3.org/2001/vcard-rdf/3.0#" xmlns:bqbiol="http://biomodels.net/biology-qualifiers/" xmlns:bqmodel="http://biomodels.net/model-qualifiers/"> <rdf:Description rdf:about="#metaid_0000004"> <bqbiol:is> <rdf:Bag> <rdf:li rdf:resource="urn:miriam:obo.chebi:CHEBI%3A15836"/> <rdf:li rdf:resource="urn:miriam:kegg.compound:C03082"/> </rdf:Bag> </bqbiol:is> </rdf:Description> </rdf:RDF> </annotation> </species>

Säg nu att jag vill ha alla species som har en länk till KEGG, då kan jag göra följande XPath-uttryck (jag är tyvärr bunden till XPath v. 1.0 för detta):

//dns:species/dns:annotation//rdf:li[contains(@rdf:resource, 'kegg')]

Detta fungerar bra (förresten kan ni bortse från prefixet dns här). Vill man söka efter species som i sina annoteringar har länkar till chebi så ändrar man ju bara strängen 'kegg' till just 'chebi'. Men om jag vill söka på species som har länkar till både kegg och chebi (som i exempel-specien ovan), hur gör man då?

Jag provade:

//dns:species[/dns:annotation//rdf:li[contains(@rdf:resource, 'chebi') and /dns:annotation//rdf:li[contains(@rdf:resource, 'kegg')]

Tanken här var att flytta upp villkoret och använda and. Men jag får syntaxfel:

Expected ], found:

Jag antar det är blanktecken som visas efter found.

Hur ska man göra?

Om nån vill göra tester på originalfilen har jag lagt upp en paste här. Kopierar ni därifrån, kopiera från rutan "update paste below" för att bara få med själva texten. Det här är curated biomodel nummer 66 och man kan ta hem alla biomodels här om man vill.

Tack för all hjälp!

Permalänk
Medlem

Det första du kan göra när det klagas på hakparanteser är att se till att de är balanserade:

//dns:species[/dns:annotation//rdf:li[contains(@rdf:resource, 'chebi')] and /dns:annotation//rdf:li[contains(@rdf:resource, 'kegg')]]

Visa signatur

Bra, snabbt, billigt; välj två.

Ljud
PC → ODAC/O2 → Sennheiser HD650/Ultrasone PRO 900/...
PC → S.M.S.L SA300 → Bowers & Wilkins 607

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av Phod
Det första du kan göra när det klagas på hakparanteser är att se till att de är balanserade:

//dns:species[/dns:annotation//rdf:li[contains(@rdf:resource, 'chebi')] and /dns:annotation//rdf:li[contains(@rdf:resource, 'kegg')]]

Ah, du har helt rätt. Jag hade inte bara ett utan två saknade hakparenteser i det uttrycket. Ett syntaxmässigt korrekt uttryck blir sålunda:

//dns:species[/dns:annotation//rdf:li[contains(@rdf:resource, 'chebi')] and /dns:annotation//rdf:li[contains(@rdf:resource, 'kegg')]]

Nåt är dock fortfarande lurt för den returnerar inga träffar som den borde på testdatan jag visade.

Permalänk
Medlem

Detta är lösningen:

//dns:species/dns:annotation[//rdf:li[contains(@rdf:resource, 'chebi')] and //rdf:li[contains(@rdf:resource, 'kegg')]]

Edit: Noterbart är ju dock att nu får man istället annoterings-elementen som svar, inte species. Det fungerar för mig i det här fallet för jag ville hitta de species som har dessa dubbel-referenser i sina annoteringar och då räcker det med annoterings-elementet som svar eftersom man lätt ser till vilken species de tillhör.

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av hivemind
Detta är lösningen:

//dns:species/dns:annotation[//rdf:li[contains(@rdf:resource, 'chebi')] and //rdf:li[contains(@rdf:resource, 'kegg')]]

Edit: Noterbart är ju dock att nu får man istället annoterings-elementen som svar, inte species. Det fungerar för mig i det här fallet för jag ville hitta de species som har dessa dubbel-referenser i sina annoteringar och då räcker det med annoterings-elementet som svar eftersom man lätt ser till vilken species de tillhör.

Hmm, nej, ropade hej för tidigt. Det blir för många träffar med den varianten. Det är nog

//rdf

dvs dubbelslashen som ställer till det men jag vet inte riktigt hur jag ska göra för vägen fram till en

<rdf:li>

kan se lite olika ut.

Permalänk
Medlem

Det slutade med att jag skrev frågan i XQuery istället, kunde använda det sen jag övertalat min chef att köpa in en licens av Saxon åt mig. Koden blev så här, tror den är rätt:

declare default element namespace "http://www.sbml.org/sbml/level2"; declare namespace rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"; declare function local:findLinks($loc as xs:string) as element()* { for $species in doc($loc)//species, $u in $species/annotation//rdf:li[contains(@rdf:resource, 'kegg')], $v in $u/..//rdf:li[contains(@rdf:resource, 'chebi')] return $species };