用java读取复杂的Xml文件

用java读取复杂的Xml文件,java,xml,xml-parsing,Java,Xml,Xml Parsing,我能够用java阅读多种类型的xml文件。但今天我得到了一个xml文件,无法读取其详细信息 <ENVELOPE> <BILLFIXED> <BILLDATE>1-Jul-2017</BILLDATE> <BILLREF>1</BILLREF> <BILLPARTY>Party1</BILLPARTY> </BILLFIXED>

我能够用java阅读多种类型的xml文件。但今天我得到了一个xml文件,无法读取其详细信息

<ENVELOPE>
    <BILLFIXED>
        <BILLDATE>1-Jul-2017</BILLDATE>
        <BILLREF>1</BILLREF>
        <BILLPARTY>Party1</BILLPARTY>
    </BILLFIXED>
    <BILLCL>-10800.00</BILLCL>
    <BILLPDC/>
    <BILLFINAL>-10800.00</BILLFINAL>
    <BILLDUE>1-Jul-2017</BILLDUE>
    <BILLOVERDUE>30</BILLOVERDUE>
    <BILLFIXED>
        <BILLDATE>1-Jul-2017</BILLDATE>
        <BILLREF>2</BILLREF>
        <BILLPARTY>Party2</BILLPARTY>
    </BILLFIXED>
    <BILLCL>-2000.00</BILLCL>
    <BILLPDC/>
    <BILLFINAL>-2000.00</BILLFINAL>
    <BILLDUE>1-Jul-2017</BILLDUE>
    <BILLOVERDUE>30</BILLOVERDUE>
    <BILLFIXED>
        <BILLDATE>1-Jul-2017</BILLDATE>
        <BILLREF>3</BILLREF>
        <BILLPARTY>Party3</BILLPARTY>
    </BILLFIXED>
    <BILLCL>-1416.00</BILLCL>
    <BILLPDC/>
    <BILLFINAL>-1416.00</BILLFINAL>
    <BILLDUE>31-Jul-2017</BILLDUE>
    <BILLOVERDUE>0</BILLOVERDUE>
</ENVELOPE>
我正在尽我所知的一切可能,但目前我无法找到任何解决办法。
如果有人有任何解决方案,请与我分享。

它不是结构良好的XML。在您的
标签中,没有任何内容指示构成“账单”的每一组六个属性的开始。通常,您希望每一个都有一个
标记来包含它们。这将使解析器感到困惑…

一种方法是“修复”XML,使其结构更加完善,例如:

//修复XML
元素envelopeElem=doc.getDocumentElement();
List children=new ArrayList();
对于(节点child=envelopeElem.getFirstChild();child!=null;child=child.getNextSibling())
添加(child);
元素billem=null;
用于(节点子节点:子节点){
if(child.getNodeType()==Node.ELEMENT\u Node&“BILLFIXED”.equals(child.getNodeName()))
envelopelem.insertBefore(billem=doc.createElement(“比尔”),子级);
if(billem!=null)
追加儿童(儿童);
}
代码基本上会在遇到
元素时创建一个新的
元素作为
的子元素,然后将所有后续节点移动到
元素中

结果是DOM树中的XML看起来像这样1,这应该更容易处理:


2017年7月1日
1.
第1方
-10800.00
-10800.00
2017年7月1日
30
2017年7月1日
2.
第2部分
-2000.00
-2000.00
2017年7月1日
30
2017年7月1日
3.
第三方
-1416.00
-1416.00
2017年7月31日
0

1) XML已重新格式化以便于人类阅读,即已重新缩进。

根据示例XML,它有3条记录的数据。但每个记录都没有任何分隔。看起来每个字段数据都填充到XML标记中并写入文件

我建议有两种可能的选择

  • 基于JAVA的:正如Andreas所建议的,读取文件内容并为每个记录添加一个根标记,这将提供有限的XML结构,从而更易于处理。当输入文件较大时,性能影响可能会增加
  • 基于转换:尝试STX转换,它可以将结构转换为所需的XML格式甚至平面文件格式。这样处理就更简单了

  • 我正在从tally服务器获取此xml。所以我们不能说它的结构不好。仅仅因为你是从现有的服务器上得到它并不意味着它是正确的。世界上到处都是坏代码!它们不是返回一个bill对象数组,而是返回一个带有一些XML标记的平面记录文件。我会采用@krishna的方法,添加一些
    标记作为记录分隔符,然后处理文件。文件大小太大,即我们可能有10000多个xml文件中的数据。对于大型文件来说,这种方式是方便的。对于大型文件,考虑使用流API和SAX解析器而不是DOM解析器来避免将其全部读入。memory@MostchRomi对于这个基于问题中使用的相同XML解析器选择的解决方案(即DOM解析器),文件怎么可能太大?如果您需要一个非DOM解决方案,那么您究竟为什么在问题中显示DOM代码,而不提及大小问题?这个答案符合这个问题。如果您有不同的问题,我建议您创建一个新问题。
    try {
              File fXmlFile = new File("filepath");
                DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
                DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
                Document doc = dBuilder.parse(fXmlFile);
                
                doc.getDocumentElement().normalize();
                NodeList billNodeList = doc.getElementsByTagName("ENVELOPE");
                for(int i=0;i<billNodeList.getLength();i++){
                    Node voucherNode = billNodeList.item(i);
                    Element voucherElement = (Element) voucherNode;
                    NodeList nList = voucherElement.getElementsByTagName("BILLFIXED");
                    
                    for (int temp = 0; temp < nList.getLength(); temp++) {
                        Node insideNode = nList.item(temp);
                        Element voucherElements = (Element) insideNode;
                        System.out.println(voucherElements.getElementsByTagName("BILLDATE").item(0).getTextContent());
                        System.out.println(voucherElements.getElementsByTagName("BILLREF").item(0).getTextContent());
                        System.out.println(voucherElements.getElementsByTagName("BILLPARTY").item(0).getTextContent());
                        System.out.println(voucherElements.getElementsByTagName("BILLFINAL").item(0).getTextContent());
                        System.out.println(voucherElements.getElementsByTagName("BILLOVERDUE").item(0).getTextContent());
                    }
                }
                
                
        } catch (Exception e) {
            e.printStackTrace();
        }