Search code examples
javaxpathvtd-xml

XPATH query to select parent based on matching child element conditon


I am trying to parse the below xml to fetch the ScId element values based on certain condition. This condition is mentioned in the xpath string and then select the ScId value in xpathNext string.

<?xml version="1.0" encoding="ISO-8859-1"?>
<SchoolData>
<School>
<ScId>SC101-91</ScId>
    <Location>
      <Branch>
        <BranchId>Br-111</BranchId>
        <Type>Residential</Type>
        <RealType>Residential</RealType>
      </Branch>
      <Branch>
        <BranchId>BR-222</BranchId>
        <Type>Daycare</Type>
        <RealType>Daycare</RealType>
      </Branch>
      <Branch>
        <BranchId>Br-333</BranchId>
        <Type>Unknown</Type>
        <RealType>Unknown</RealType>
      </Branch>
    </Location>
</School>

<School>
<ScId>RC101-92</ScId>
    <Location>
      <Branch>
        <BranchId>Br-111</BranchId>
        <Type>Residential</Type>
        <RealType>Residential</RealType>
      </Branch>
      <Branch>
        <BranchId>BR-222</BranchId>
        <Type>Daycare</Type>
        <RealType>Daycare</RealType>
      </Branch>
      <Branch>
        <BranchId>Br-333</BranchId>
        <Type>Unknown</Type>
        <RealType>Unknown</RealType>
      </Branch>
    </Location>
</School>
</SchoolData>

I'm using nested xpath query using VTD xml parser to fetch the ScId value which start with RC and Type = Daycare.

Below is the code

String xpath = "/*/School[starts-with(ScId,'RC')]/Location/Branch[Type='Daycare']";
        String xml = "/school.xml";
        
        final VTDGenHuge vg = new VTDGenHuge();
        System.out.println("Parsing");
        vg.parseFile(xml, true, VTDGenHuge.MEM_MAPPED);

        VTDNavHuge vn = vg.getNav();

        AutoPilotHuge aph = new AutoPilotHuge(vn);
        String xpathNext = "concat(//ScId,'-NEW')";
        aph.selectXPath(xpath);
        while ((aph.evalXPath()) != -1) {
            getparsedValue(vn,xpathNext);
            
        }

and parsing logic is

private static String getparsedValue(final VTDNavHuge vn, String xpath) throws NavException,

    XPathParseException, XPathEvalException, XPathParseExceptionHuge, XPathEvalExceptionHuge, NavExceptionHuge{

        String value = null;
        vn.push();
        
        AutoPilotHuge ap = new AutoPilotHuge(vn);
        ap.selectXPath(xpath);

        ap.bind(vn);
        value = ap.evalXPathToString();
        System.out.println("parsed value is " +value);
        vn.pop();
        return value;
    }

This returns me

parsed value is SC101-91-NEW

while I'm expecting it to be

parsed value is RC101-92-NEW


Solution

  • Maybe this XPath-1.0 expression helps you. I have no Java available to test it.

    /*/School[starts-with(ScId,'RC') and Location/Branch[Type='Daycare']]
    

    This iterates over all <School> elements that satisfy the conditions.
    To get the <ScId>, add the string /ScId to the end of the expression.