当前位置: 首页 > 知识库问答 >
问题:

我如何使用Java DOM从嵌套XML中提取数据?

丌官和泰
2023-03-14

我有一个xml文档,它有多个。我能够得到和帐户的详细信息(,等。我很难得到像card_type、年、月、first_six等的东西。

这个文档中有200个事务,因此是循环。

  <transaction href="https://test.com" type="cc">
    <source>subscription</source>
    <created_at type="datetime">2014-03-06T20:59:03Z</created_at>
    <details>
      <account>
        <account_code>234234234</account_code>
        <first_name>asdadad</first_name>
        <last_name>asdadasd3433</last_name>
        <company nil="nil"></company>
        <email>test@gmail.com</email>
        <billing_info type="credit_card">
          <first_name>asdasdasd</first_name>
          <last_name>asdasdasd23434</last_name>
          <address1 nil="nil"></address1>
          <address2 nil="nil"></address2>
          <city nil="nil"></city>
          <state nil="nil"></state>
          <zip nil="nil"></zip>
          <country nil="nil"></country>
          <phone nil="nil"></phone>
          <vat_number nil="nil"></vat_number>
          <card_type>Visa</card_type>
          <year type="integer">2039</year>
          <month type="integer">6</month>
          <first_six>111111</first_six>
          <last_four>9999</last_four>
        </billing_info>
      </account>
    </details>
    <a name="refund" href="https://test.com/refund" method="delete"/>
  </transaction>

我在尝试代码时遇到以下错误:

java.lang.NullPointerException
        at test.test.getTransactions(test.java:288)
        at test.test.main(test.java:53)

以下是我正在尝试的:

try {
  NodeList nList2 = eElement.getElementsByTagName("details");
  Node nNode2 = nList2.item(0);
  Element eElement2 = (Element) nNode2;

  //get some other info in try catch blocks here (removed for reading)

  try {
    System.out.println("attempting billing info");
    NodeList nList3 = eElement2.getElementsByTagName("billing_info");
    Node nNode3 = nList3.item(0);
    Element eElement3 = (Element) nNode3;    
    System.out.println("attempting credit_year");
    System.out.println("credit_year: " + eElement3.getElementsByTagName("credit_year").item(0).getTextContent());
  } catch (Exception ex) {
    ex.printStackTrace();
  }

}

共有2个答案

微生欣怡
2023-03-14

可以使用声明式流映射(DSM)流解析库轻松解析复杂的XML。

您只需定义要从XML中提取的数据的映射

下面是XML的映射定义。

DSM忽略命名空间。

result:     
   type: array
   path: /transactions/transaction       
   fields:
       source:          
       account:
          type: array
          path: details/account
          fields:       
             accountCode: 
               path: account_code                 
             firstName: 
               path: first_name                 
             lastName: 
               path: last_name                 
             first_six: 
               path: billing_info/first_six
               dataType: int                 
             last_four: 
               path: billing_info/last_four
               dataType: int                 
             card_type: 
               path: billing_info/card_type

解析XML的Java代码:

DSM dsm=new DSMBuilder(new File("path/to/mapping.yaml")).setType(DSMBuilder.TYPE.XML).create();
Object result=  dsm.toObject(xmlFileContent);
// json represntation fo result
dsm.getObjectMapper().writerWithDefaultPrettyPrinter().writeValue(System.out, object);

下面是输出:

[ {
  "source" : "subscription",
  "account" : [ {
    "accountCode" : "234234234",
    "firstName" : "asdadad",
    "lastName" : "asdadasd3433",
    "card_type" : "Visa",
    "first_six" : 111111,
    "last_four" : 9999
  } ]
} ]

如果要直接反序列化到POJO类,则可以使用DSM

宗政昱
2023-03-14

下面是一些可以指导您使用DOM解析XML文件的代码。你错过了文档生成器。

    //Build the document from the xmlString
    DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
    Document doc = dBuilder.parse(new InputSource(new StringReader(xmlString)));

    //Get all the transaction elements and then loop over them
    NodeList transaction = doc.getElementsByTagName("transaction");
    for(int j = 0; j < transaction.getLength(); j++) {
        //Traverse down the transaction node till we get the billing info
        NodeList details = ((Element)transaction.item(j)).getElementsByTagName("details");
        NodeList account = ((Element)details.item(0)).getElementsByTagName("account");
        NodeList billinginfo = ((Element)account.item(0)).getElementsByTagName("billing_info");

        System.out.println("===Billing Info===");
        System.out.println("Type: "+((Element)billinginfo.item(0)).getAttribute("type"));

        //Get all children nodes from billing info
        NodeList billingChildren = billinginfo.item(0).getChildNodes();

        for(int i = 0; i < billingChildren.getLength(); i++) {
            Node current = billingChildren.item(i);
            //Only want stuff from ELEMENT nodes
            if(current.getNodeType() == Node.ELEMENT_NODE) {
                System.out.println(current.getNodeName()+": "+current.getTextContent());
            }
        }
    }

这将从您的示例中生成以下内容。

===Billing Info===
Type: credit_card
first_name: asdasdasd
last_name: asdasdasd23434
address1:
address2:
city:
state:
zip:
country:
phone:
vat_number:
card_type: Visa
year: 2039
month: 6
first_six: 111111
last_four: 9999
 类似资料:
  • 这里我有两个文档,我需要查询以获得和我只想获得符合以上条件的注释。并非所有评论。 ' { “_id”: ObjectId(“53b7f2383ed7755c2400002e”), “title”: “Post One”, “author”: “bob”, “posted”: ISODate(“2014-07-05T12:40:24.0Z”), “pageViews”: NumberInt(5),

  • 我在弄清楚如何从apache Olingo构建的uri中提取数据时遇到了问题。从$Expad中提取数据可以使用这种语法。 URI:OData/PropertyOrigin?$expand=Property1($select=field1);$expand=Property2($select=field1ofProperty2)) 但是,当我试图从第二个$Expand中获取数据时,我得到了一个对象空

  • 问题内容: 我正在尝试从数据JSON获取值。我已经成功遍历了JSON数据,几乎满足了我的需求! 在Python中运行以下命令: 给我这个: 我只想获得价值。这是关键。 如何进一步执行命令以仅返回值? 问题答案: 这是完整的输出吗?这本字典包含带有嵌套字典的列表,因此您应该这样处理。假设它被称为: 您的第一个地址是对象,然后是字典中的键,列表中的索引以及该字典的键: 输出: 编辑:根据您所得到的然后

  • 然后连空白节点都是嵌套的,这是我不想要的。有什么方法可以使用Jena获得这种结构吗?或者有没有其他的Java库可以更好地处理这一点?

  • 我有下一个带嵌套括号的字符串: 我想用打印出来的每个括号的值填充一个数组: