Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Filter XPath list based on values in associated list

Tags:

xpath

Given this XML

<DiagList>
    <Diag id="1" icd="400"/>
    <Diag id="2" icd="401"/>
    <Diag id="3" icd="402"/>
    <Diag id="4" icd="400"/>
</DiagList>
<ICDList>
    <ICD id="400" description="First one"/>
    <ICD id="401" description="Second one"/>
    <icd id="402" description="Third one"/>
<ICDList>

I want to write an Xpath query that will select Diags where the associated ICD's description contains some text.

So for instance if I specified text of "st" then I should get Diags "1" and "4". If I specify text of "ir" I should get diags "1", "3", and "4".

I tried

/DiagList/Diag[contains(lcase(/ICDList/ICD[@id=/DiagList/Diag/@icd]/@description), 'st')]

and variations.

I haven't been able to get it to work. Seems it doesn't like the nested reference to @icd.

Is this something that is possible?

thanks ben

like image 488
Ben Spigle Avatar asked Nov 10 '11 22:11

Ben Spigle


1 Answers

Use:

   /*/DiagList
         /*
          [@icd
          =
           /*/ICDList/*
                [contains(@description, $pText)]
                   /@id
          ]

where $pText must be substituted with the desired string literal.

XSLT - based verification:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:my="my:my ">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:param name="pText" select="'ir'"/>

 <xsl:template match="/">
  <xsl:copy-of select=
  "/*/DiagList
         /*
          [@icd
          =
           /*/ICDList/*
                [contains(@description, $pText)]
                   /@id
          ]"/>
 </xsl:template>
</xsl:stylesheet>

when this transformation is applied on the provided XML document (corrected to be mede well-formed):

<t>
    <DiagList>
        <Diag id="1" icd="400"/>
        <Diag id="2" icd="401"/>
        <Diag id="3" icd="402"/>
        <Diag id="4" icd="400"/>
    </DiagList>
    <ICDList>
        <ICD id="400" description="First one"/>
        <ICD id="401" description="Second one"/>
        <icd id="402" description="Third one"/>
    </ICDList>
</t>

the wanted nodes are selected and copied to the output:

<Diag id="1" icd="400" />
<Diag id="3" icd="402" />
<Diag id="4" icd="400" />

when we set in the above transformation:

 <xsl:param name="pText" select="'st'"/>

then again the wanted result is produced:

<Diag id="1" icd="400" />
<Diag id="4" icd="400" />
like image 61
Dimitre Novatchev Avatar answered Dec 23 '22 12:12

Dimitre Novatchev