【问题标题】:How to parse an XML file where there are two different transactions with all same sub tags but one tag is different using DOM parser in JAVA?如何使用 JAVA 中的 DOM 解析器解析一个 XML 文件,其中有两个不同的事务具有所有相同的子标签但一个标签不同?
【发布时间】:2016-04-02 05:17:25
【问题描述】:

我有一个如下的 XML 文档:

<Transactions>
<Transaction>
  <TransactionType>Account Payable</TransactionType>
  <TransactionFor>Supplier</TransactionFor>
  <TransactionDate>09/11/2015 00:40:31</TransactionDate>
  <ItemReference>Hotels</ItemReference>
  <Amount>3420.00</Amount>
  <AmountPaid>0.00</AmountPaid>
  <Balance>3420.00</Balance>
  <Status>Open</Status>
  <SupplierID>3930d9cd-1d8a-4e4d-99d3-4cd4b208795d</SupplierID>
</Transaction>
<Transaction>
  <TransactionType>Account Receivable</TransactionType>
  <TransactionFor>Consumer</TransactionFor>
  <TransactionDate>09/11/2015 00:40:31</TransactionDate>
  <ItemReference>Hotels</ItemReference>
  <Amount>3420.00</Amount>
  <AmountPaid>3420.00</AmountPaid>
  <Balance>0.00</Balance>
  <Status>Closed</Status>
  <ConsumerID>65e3dbb6-4353-4fbb-8e8b-28d0c09dc728</ConsumerID>
</Transaction>
</Transactions>

当一个标签不同时,例如supplierIdconsumerId,我如何在 Java 中解析这个?

我已经实现了这个代码,但是得到了NullPointerException

NodeList nList8 = doc.getElementsByTagName("Transaction");

for (int temp8 = 0; temp8 < nList8.getLength(); temp8++) 
{
    Node nNode8 = nList8.item(temp8);
    if (nNode8.getNodeType() == Node.ELEMENT_NODE) 
    {
        Element eElement8 = (Element) nNode8;                       
        System.out.println("TransactionType : " + eElement8.getElementsByTagName("TransactionType").item(0).getTextContent());
        System.out.println("TransactionFor : " + eElement8.getElementsByTagName("TransactionFor").item(0).getTextContent());
        System.out.println("TransactionDate : " + eElement8.getElementsByTagName("TransactionDate").item(0).getTextContent());
        System.out.println("ItemReference : " + eElement8.getElementsByTagName("ItemReference").item(0).getTextContent());
        System.out.println("Amount : " + eElement8.getElementsByTagName("Amount").item(0).getTextContent());
        System.out.println("AmountPaid : " + eElement8.getElementsByTagName("AmountPaid").item(0).getTextContent());
        System.out.println("Balance : " + eElement8.getElementsByTagName("Balance").item(0).getTextContent());
        System.out.println("Status : " + eElement8.getElementsByTagName("Status").item(0).getTextContent());
        if(eElement8.getElementsByTagName("SupplierID").item(0).getTextContent()==null)
        {
            System.out.println("ConsumerID : " + eElement8.getElementsByTagName("ConsumerID").item(0).getTextContent());    
        }
        else if(eElement8.getElementsByTagName("ConsumerID").item(0).getTextContent() == null)
            System.out.println("SupplierID : " + eElement8.getElementsByTagName("SupplierID").item(0).getTextContent());
    }
}

【问题讨论】:

  • @SyedAqib 您在 NodeList nList8 = doc.getElementsByTagName("Transaction"); 中得到空指针异常;这一行 measn doc 为 null.. 尝试调试

标签: java xml parsing dom


【解决方案1】:

出现问题是因为您在测试父元素(SupplierIDConsumerID)是否存在之前尝试通过.item(0).getTextContent() 访问子节点:

            if (eElement8.getElementsByTagName("SupplierID").item(0).getTextContent() == null)
            {

            } else if (eElement8.getElementsByTagName("ConsumerID").item(0).getTextContent() == null) {

            }

您采用的方法是合理的,但是您需要在遍历树时在每个级别执行空值检查。最终,您应该从您正在使用的顶级元素开始,然后逐步向下处理一个元素。

如果您想跳过空值检查,最好先根据架构或 DTD(如果存在)验证您的文档,以确保文档符合预期的结构,然后再尝试访问节点。不过上面的代码还是有问题的。

我建议通过以下方式将您的解析与业务逻辑分开(原始方法是parse1(),新方法是parse2()):

import java.io.File;
import java.io.FileInputStream;

import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class DomTest
{
    public static void main(String[] args)
    {
        File iFile = new File("src/main/resources/domtest.xml");

        try
        {
            Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new FileInputStream(iFile));

            new DomTest().parse2(doc);
        } catch (Exception e) {
            e.printStackTrace();

            System.out.println("Failed to parse " + iFile.getAbsolutePath());
            System.exit(1);
        }

        System.exit(0);
    }

    public void parse1(Document doc)
    {
        NodeList nList8 = doc.getElementsByTagName("Transaction");

        for (int temp8 = 0; temp8 < nList8.getLength(); temp8++) 
        {
            Node nNode8 = nList8.item(temp8);

            if (nNode8.getNodeType() == Node.ELEMENT_NODE) 
            {
                Element eElement8 = (Element) nNode8;   

                System.out.println("TransactionType : " + eElement8.getElementsByTagName("TransactionType").item(0).getTextContent());
                System.out.println("TransactionFor : " + eElement8.getElementsByTagName("TransactionFor").item(0).getTextContent());
                System.out.println("TransactionDate : " + eElement8.getElementsByTagName("TransactionDate").item(0).getTextContent());
                System.out.println("ItemReference : " + eElement8.getElementsByTagName("ItemReference").item(0).getTextContent());
                System.out.println("Amount : " + eElement8.getElementsByTagName("Amount").item(0).getTextContent());
                System.out.println("AmountPaid : " + eElement8.getElementsByTagName("AmountPaid").item(0).getTextContent());
                System.out.println("Balance : " + eElement8.getElementsByTagName("Balance").item(0).getTextContent());
                System.out.println("Status : " + eElement8.getElementsByTagName("Status").item(0).getTextContent());

                if (eElement8.getElementsByTagName("SupplierID").item(0).getTextContent() == null)
                {
                    System.out.println("ConsumerID : " + eElement8.getElementsByTagName("ConsumerID").item(0).getTextContent());                                    
                } else if (eElement8.getElementsByTagName("ConsumerID").item(0).getTextContent() == null) {
                    System.out.println("SupplierID : " + eElement8.getElementsByTagName("SupplierID").item(0).getTextContent());
                }
            }
        }

        return;
    }

    public void parse2(Document doc)
    {
        Element transactionsEl = doc.getDocumentElement();

        NodeList transactionEls = transactionsEl.getElementsByTagName("Transaction");

        for (int txIdx = 0; txIdx < transactionEls.getLength(); txIdx++) 
        {
            // we know that this an Element node because we used getElementsByTagName above
            Element transactionEl = (Element) transactionEls.item(txIdx);

            String transactionType = null;
            String transactionFor = null;
            String transactionDate = null;
            String itemReference = null;
            String amount = null;
            String amountPaid = null;
            String balance = null;
            String status = null;
            String consumerID = null;
            String supplierID = null;

            NodeList transactionElChildNodes = transactionEl.getChildNodes();

            for (int i = 0; i < transactionElChildNodes.getLength(); i++)
            {
                Node n = transactionElChildNodes.item(i);

                if (n.getNodeType() == Node.ELEMENT_NODE)
                {
                    Element someEl = (Element) n;

                    String elName = someEl.getTagName();
                    String text = someEl.getTextContent();

                    if (elName.equals("TransactionType"))
                    {
                        transactionType = text;
                    } else if (elName.equals("TransactionFor")) {
                        transactionFor = text;
                    } else if (elName.equals("TransactionDate")) {
                        transactionDate = text;
                    } else if (elName.equals("ItemReference")) {
                        itemReference = text;
                    } else if (elName.equals("Amount")) {
                        amount = text;
                    } else if (elName.equals("AmountPaid")) {
                        amountPaid = text;
                    } else if (elName.equals("Balance")) {
                        balance = text;
                    } else if (elName.equals("Status")) {
                        status = text;
                    } else if (elName.equals("SupplierID")) {
                        supplierID = text;
                    } else if (elName.equals("ConsumerID")) {
                        consumerID = text;
                    }
                }
            }

            // business logic follows:

            System.out.println("Transaction " + String.valueOf(txIdx));

            if (supplierID != null)
            {
                System.out.println("SupplierID: " + supplierID);
            }

            if (consumerID != null)
            {
                System.out.println("ConsumerID: " + consumerID);
            }
        }

        return;
    }
}

结果:

Transaction 0
SupplierID: 3930d9cd-1d8a-4e4d-99d3-4cd4b208795d 
Transaction 1
ConsumerID: 65e3dbb6-4353-4fbb-8e8b-28d0c09dc728

【讨论】:

  • 感谢 vallis 的解决方案 :)
【解决方案2】:

XML 表示可扩展标记语言

1 你可以将任何结构、任何树和任何节点放在一个 xml 文件中,只要它们遵守简单的规则:打开标签必须有一个对称的结束标签,对字符有一些限制。 p>

它真的很开放,你可以放 Mo (Go ?),而且由于打开/关闭标签,它很健壮。

您可以进一步添加新数据,而不会破坏您的应用程序(下一点)。

2 然后你可以解析它们

在 SO 上搜索一些解析器和示例。还要看看 xpath。

你解析并得到你想要的。如果数据太多,你会忘记它们(或者如果你想要严格的格式......)。

3 请注意,标签不是唯一的:您可以重复他(甚至在子级别使用它,甚至使用相同的标签进行子标记)。

4 那么问题可能出在您的设计中,以及您在解析时想要做什么。

如果一个元素有一个标签 (supplierId) 而另一个没有,你想做什么?创建不同的对象,以不同的方式处理?这取决于你。

5 如果您希望对接受的数据和结构有严格的规定,您还可以使用 DTD/XML 模式以及工具和库来检查 xml 输入。

希望对你有帮助。

【讨论】:

    猜你喜欢
    • 2015-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-04
    • 1970-01-01
    • 1970-01-01
    • 2012-10-05
    • 1970-01-01
    相关资源
    最近更新 更多