【问题标题】:How to get relative depth of XML element using XPATH如何使用 XPATH 获取 XML 元素的相对深度
【发布时间】:2015-09-26 15:38:03
【问题描述】:

我试图从给定 XML 文件中的特定元素中找到给定 XML 元素的相对深度,我尝试使用 XPATH,但我对 XML 解析不是很熟悉,也没有得到想要的结果。我还需要在计数时忽略数据元素。

以下是我编写的代码和示例 XML 文件。 例如。 NM109_BillingProviderIdentifierTS837_2000A_Loop 元素的深度为 4。

父节点为:TS837_2000A_Loop < NM1_SubLoop_2 < TS837_2010AA_Loop < NM1_BillingProviderName 因为NM109_BillingProviderIdentifierNM1_BillingProviderName 的子级,因此NM1_BillingProviderNameTS837_2000A_Loop 的相对深度为4(包括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>     

【问题讨论】:

  • 4412 个字符的单行 XML?超过 4kB?请花点时间 (1) 将您的示例 XML 最小化为理解您的问题所需的内容,以及 (2) 对您的示例进行布局,使其易于阅读。请花一分钟阅读minimal reproducible example。另外,请说明“相对位置”。人物定位?节点位置?深度?

标签: java xml xpath


【解决方案1】:

获取任何节点深度的关键方法是计算其祖先(包括父节点、父节点的父节点等):

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

这会给你计数到根。要获得 relative 计数,即从根以外的任何地方,假设名称不重叠,您可以这样做:

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

根据是否应将当前元素或基本元素包含在计数中,使用ancestor-or-selfancestor 轴。


PS:您可能应该感谢Pietro Saccardi 如此友好地使您的帖子和巨大的(一行4kB ..)示例XML 可读。

【讨论】:

  • @Pietro Saccardi :非常感谢您使我的帖子具有可读性。在写我以后的帖子时,我会牢记这一点。
  • 我尝试了您建议的表达式,但计数始终为 0。我的代码有什么问题吗?
  • 我错过了 // 在 NM109_BillingProviderIdentifier 前面,它现在给我计数。让我测试我正在开发的功能。谢谢。
  • @DaisyD,添加// 表示“在树中任意深度搜索”。我不知道您的全部要求,但如果您有多个要搜索的元素,您可能希望在每次使用 XPath 时放入一个循环并将焦点设置到父元素。如果是这种情况,您最好使用 XSLT,这在此类任务中要容易得多(但需要您,嗯,学习 XSLT...)
  • 我还需要考虑除叶节点之外的先验元素。例如。对于 N301_BillingProviderAddressLine,应考虑 NM1_BillingProviderName,计数应为 5。
猜你喜欢
  • 2021-12-28
  • 1970-01-01
  • 2017-01-20
  • 2014-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-07
相关资源
最近更新 更多