How to get relative depth of XML element using XPA

2020-04-13 18:22发布

问题:

I am trying to find the relative depth of given XML element from specific element in the given XML file, I tried to use XPATH but I'm not very familiar with XML parsing and I'm not getting the desired result. I need as well to ignore the data elements while counting.

Below is the code that I have written and the sample XML file. E.g. the depth of NM109_BillingProviderIdentifier from TS837_2000A_Loop element is 4.

The parent nodes are: TS837_2000A_Loop < NM1_SubLoop_2 < TS837_2010AA_Loop < NM1_BillingProviderName as NM109_BillingProviderIdentifier is a child of NM1_BillingProviderName and thus the relative depth of NM1_BillingProviderName from TS837_2000A_Loop is 4 (including TS837_2000A_Loop).

package com.xmlexamples;
import java.io.File;
import java.io.FileInputStream;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;


public class XmlParser {

public static void main(String[] args) throws Exception {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setValidating(false);
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document doc = db.parse(new FileInputStream(new File("D://sample.xml")));

        XPathFactory factory = XPathFactory.newInstance();
        XPath xpath = factory.newXPath();
        String expression;      
        expression = "count(NM109_BillingProviderIdentifier/preceding-sibling::TS837_2000A_Loop)+1";                
        Double d = (Double) xpath.compile(expression).evaluate(doc, XPathConstants.NUMBER);     
        System.out.println("position from  TS837_2000A_Loop " + d);

    }
}

<?xml version='1.0' encoding='UTF-8'?>
<X12_00501_837_P xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <TS837_2000A_Loop>
        <NM1_SubLoop_2>
            <TS837_2010AA_Loop>
                <NM1_BillingProviderName>
                    <NM103_BillingProviderLastorOrganizationalName>VNA of Cape Cod</NM103_BillingProviderLastorOrganizationalName>
                    <NM109_BillingProviderIdentifier>1487651915</NM109_BillingProviderIdentifier>
                </NM1_BillingProviderName>
                <N3_BillingProviderAddress>
                  <N301_BillingProviderAddressLine>8669 NORTHWEST 36TH ST </N301_BillingProviderAddressLine>
                </N3_BillingProviderAddress>
            </TS837_2010AA_Loop>
        </NM1_SubLoop_2>
    </TS837_2000A_Loop>
</X12_00501_837_P>     

回答1:

The pivotal method for getting the depth of any node is by counting its ancestors (which include the parent, the parent of the parent etc):

count(NM109_BillingProviderIdentifier/ancestor-or-self::*)

This will give you the count up to the root. To get the relative count, i.e. from anything other than the root, assuming the names do not overlap, you can do this:

count(NM109_BillingProviderIdentifier/ancestor-or-self::*)
- count(NM109_BillingProviderIdentifier/ancestor::TS837_2000A_Loop/ancestor::*)

Depending on whether the current, or the base element should be included in the count, use the ancestor-or-self or ancestor axis.


PS: you should probably thank Pietro Saccardi for so kindly making your post and your huge (4kB on one line..) sample XML readable.



标签: java xml xpath