【问题标题】:DOM4J Parse not returning any child nodesDOM4J Parse 不返回任何子节点
【发布时间】:2016-01-28 20:25:13
【问题描述】:

我正在尝试开始编写一个使用 DOM4j 的程序,我希望用它来解析 XML 文件,将其保存到一些表中,最后允许用户操作数据。

不幸的是,我被困在最基本的步骤,解析。

这是我试图包含的 XML 的一部分:

<?xml version="1.0"?>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.054.001.04">

   <BkToCstmrDbtCdtNtfctn>

        <GrpHdr>

            <MsgId>000022222</MsgId>

当我尝试查找我的 XML 的根时,它确实将根正确地返回为“文档”。当我尝试从 Document 获取子节点时,它也正确地给了我“BkToCstmrDbtCdtNtfctn”。问题是,当我尝试进一步从“Bk”获取子节点时,我做不到。我在控制台中得到了这个:

org.dom4j.tree.DefaultElement@2b05039f [Element: <BkToCstmrDbtCdtNtfctn uri: urn:iso:std:iso:20022:tech:xsd:camt.054.001.04 attributes: []/>]

这是我的代码,如有任何反馈,我将不胜感激。最终我想取回“MsgId”属性,但总的来说,我只想弄清楚如何更深入地解析 XML,因为实际上它可能有大约 25 层。

public static Document getDocument(final String xmlFileName){

        Document document = null;
        SAXReader reader = new SAXReader();
        try{
            document = reader.read(xmlFileName);
        }
        catch (DocumentException e)
        {
            e.printStackTrace();
    }
        return document;
    }

    public static void main(String args[]){

        String xmlFileName = "C:\\Users\\jhamric\\Desktop\\Camt54.xml";
        String xPath = "//Document";
        Document document = getDocument(xmlFileName);
        Element root = document.getRootElement();
        List<Node> nodes = document.selectNodes(xPath);

        for(Iterator i = root.elementIterator(); i.hasNext();){
            Element element = (Element) i.next();
            System.out.println(element);

        }

        for(Iterator i = root.elementIterator("BkToCstmrDbtCdtNtfctn");i.hasNext();){
            Element bk = (Element) i.next();
            System.out.println(bk);
        }
    }

}

【问题讨论】:

  • 快速猜测:你的根节点上有一个命名空间,但你没有使用命名空间查询子节点。

标签: java dom4j


【解决方案1】:

最好的方法可能是使用 XPath,但由于 XML 文档使用名称空间,因此您不能使用 API 中的“简单”selectNodes 方法。我将创建一个辅助方法来轻松评估 DocumentElement 级别上的任何 XPath 表达式:

public static void main(String[] args) throws Exception {

    Document doc = getDocument(...);

    Map<String, String> namespaceContext = new HashMap<>();
    namespaceContext.put("ns", "urn:iso:std:iso:20022:tech:xsd:camt.054.001.04");

    // Select the first GrpHdr element in document order
    Element element = (Element) select("//ns:GrpHdr[1]", doc, namespaceContext);
    System.out.println(element.asXML());

    // Select the text content of the MsgId element
    Text msgId = (Text) select("./ns:MsgId/text()", element, namespaceContext);
    System.out.println(msgId.getText());

}

static Object select(String expression, Branch contextNode, Map<String, String> namespaceContext) {
    XPath xp = contextNode.createXPath(expression);
    xp.setNamespaceURIs(namespaceContext);
    return xp.evaluate(contextNode);
}

请注意,XPath 表达式必须使用映射到输入文档中使用的命名空间 URI 的命名空间前缀,但前缀的实际值无关紧要。

【讨论】:

  • 谢谢。实际上,由于命名空间混乱,我决定切换回标准 DOM,但如果我需要回到 4J,我会毫不犹豫地使用它。
  • 但是命名空间的东西在 DOM 中基本上是一样的,还是你作弊并使用了没有命名空间支持的 DocumentBuilderFactory :)?
  • 我使用了 DocumentBuilderFactory :) 希望在用户进行更改后我必须实际重新保存 XML 时,它不会再次困扰我。
猜你喜欢
  • 1970-01-01
  • 2012-10-07
  • 1970-01-01
  • 2017-02-02
  • 1970-01-01
  • 2023-03-12
  • 1970-01-01
  • 1970-01-01
  • 2012-12-28
相关资源
最近更新 更多