【问题标题】:Parser to parse unknown XML Schema in java解析器在 java 中解析未知的 XML Schema
【发布时间】:2017-09-14 19:28:28
【问题描述】:

我尝试理解 stackoverflow 中的所有其他答案。但我无法将这些答案与我的问题联系起来。

当我调用网络服务时,我得到response。我通过response.getData();(The XML of the data table containing the results.) (return type String) 获得架构。我们不知道我们在那个 XML 中得到了什么数据。

我需要使用第 3 方解析器,因此当我将上述字符串提供给该解析器中的一个方法时,它应该返回该 XML 中的所有元素,然后我可以打印所需的元素。

我不想自己开始解析 XML。有没有办法我可以做到这一点? (它甚至有任何意义吗?)。对不起,如果我完全错了。 (使用Axis2/eclipse)(已编辑)

编辑:添加我已经尝试过的代码。

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
NodeList nodeList = null;


        try {
            String xml = res2.getResult().getRawData();
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document document = db.parse(new ByteArrayInputStream(xml.getBytes()));
            nodeList = document.getElementsByTagName("PhoneNumber");
            NamedNodeMap attrib = document.getAttributes();
            for (int i = 0; i < attrib.getLength(); i++) {
                String nodeName = attrib.item(i).getNodeName();
                //nodeName
                String nodeValue = attrib.item(i).getNodeValue();
            }

但我不确定电话号码是否带有该标签或其他名称。我们也不知道我们有多少标签。

谢谢,使用 SyamS 的代码,我可以从 xml 打印所有节点和相应的值。现在我想将它存储到一个哈希图中,键为节点名,节点值在列表中。

示例 XML:

<Docs>
<Doc>
<Id>12</Id>
<Phone>1234</Phone>
</Doc>
<Doc>
<Id>147</Id>
<Phone>12345</Phone>
<Locked>false</Locked>
<BID>2</BID>
<DocId>8</DocId>
<Date>2014-02-04T12:18:50.063-07:00</Date>
<Urgent>false</Urgent>
</Doc>
</Docs>

【问题讨论】:

  • 为什么要解析 XML Schema ?我假设您要处理 XML 中的响应,并且“必需元素”是此 XML 数据文件中的元素? (XML 模式定义 XML 数据文件的结构。)
  • 您好,请查看我的问题中的编辑。忘记架构。我得到了 DataTable 的 XML。现在我需要从那个 xml 中获取数据(比如用户名、id、ssn、电子邮件,我们不知道我们在那个 xml 中得到了什么其他数据)。现在我想要解析它,这样我就可以获得他们发送的所有结果并使用所需的结果。
  • @Jenny 我正在考虑可以编写的类来处理这个问题。您的 XML 存储在什么对象中?我想知道如何将 XML 传递给方法参数或类构造函数。
  • 我会将传入的数据(作为字符串)存储到 file.xml 中。这样我就可以将此 xml 文件提供给解析和打印所有属性及其值的解析器。 (我假设这就是它的工作原理。)

标签: java xml parsing


【解决方案1】:

您无需为此使用第三方库。您可以简单地使用 xpath 识别所有叶节点并读取值(以及属性)。例如

public static Map<String, List<String>> parseXml(String xml) throws XMLStreamException {
    StringBuilder content = null;
    Map<String, List<String>> dataMap = new HashMap<>();
    XMLInputFactory factory = XMLInputFactory.newInstance();
    InputStream stream = new ByteArrayInputStream(xml.getBytes());
    XMLStreamReader reader = factory.createXMLStreamReader(stream);

    while (reader.hasNext()) {
        int event = reader.next();

        switch (event) {
            case XMLStreamConstants.START_ELEMENT:
                content = new StringBuilder();
                break;

            case XMLStreamConstants.CHARACTERS:
                if (content != null) {
                    content.append(reader.getText().trim());
                }
                break;

            case XMLStreamConstants.END_ELEMENT:
                if (content != null) {
                    String leafText = content.toString();
                    if(dataMap.get(reader.getLocalName()) == null){
                        List<String> values = new ArrayList<>();
                        values.add(leafText);
                        dataMap.put(reader.getLocalName(), values);
                    } else {
                        dataMap.get(reader.getLocalName()).add(leafText);
                    }
                }
                content = null;
                break;

            case XMLStreamConstants.START_DOCUMENT:
                break;
        }

    }

    return dataMap;
}

【讨论】:

  • 谢谢。但是 XPath 是否也将文件加载到内存中?我们将接收大型 XML 文件,我们不希望它加载到内存中。我写的代码被拒绝了,原因和我使用 DOM 一样。
  • 是的。它是一个 DOM 模型。如果您必须处理大型 xml,您可能需要查看 SAX 解析器或 StAX 解析器。使用 StAx 解析器解决方案更新我的答案。
  • 谢谢赛姆。我会试试这个:)
  • 太棒了!现在我遇到了一个不同的问题。如果我的 xml 有 3 个节点,例如姓名、电子邮件和电话,那么我可以将它们保存到 pojo 类中。但是现在的情况是我们不知道传入的 xml 中有哪些所有数据。我该如何存储它?
  • 我不完全理解这个问题。您可以获取节点名称。因此,如果节点名称为“email” ans 等,您可以编写一个 switch 语句来设置 pojo 的电子邮件字段。如果您可以提供一个示例 xml,我可以尝试创建 pojo。
【解决方案2】:

您应该阅读与Best XML parser for Java 相关的答案。使用来自Sample XML File (books.xml) 的示例 XML(我已下载到我的 C: 驱动器上的临时文件夹),您可能会使用 Java 的本机 SAXParser 库。这是一个示例类,您可以使用它来遍历 XML 中的所有元素。在您的项目中创建该类,并将其 parse 方法调用为:

File xml = new File("c:/temp/books.xml");
MySaxParser sax = new MySaxParser(xml);
sax.parseXml();

这是您可以复制到项目中以试用的类。当然,根据您的需要进行修改。导入应将您引导至适当的 Java API 页面,例如 Class SAXParser

import java.io.File;
import java.io.IOException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class MySaxParser extends DefaultHandler {
    private String absolutePathToXml = "";
    public MySaxParser(File xml) {
        absolutePathToXml = xml.getAbsolutePath();
    }
    /**
     * Parses an XML file into memory
     */
    public void parseXml() {
        SAXParserFactory factory = SAXParserFactory.newInstance();
        try {
            SAXParser parser = factory.newSAXParser();
            parser.parse(absolutePathToXml, this);
        } catch (ParserConfigurationException e) {
            System.out.println("ParserConfigurationException: ");
            e.printStackTrace();
        } catch (SAXException e) {
            System.out.println("SAXException: ");
            e.printStackTrace();
        } catch (IOException e) {
            System.out.println("IOException: ");
            e.printStackTrace();
        }
    }
    /**
     * Event: Parser starts reading an element
     */
    @Override
    public void startElement(String s1, String s2, String elementName, Attributes attributes) 
            throws SAXException {
        //print an element's name
        System.out.println("element: " + elementName);
        //print all attributes for this element
        for(int i = 0; i < attributes.getLength(); i++) {
            System.out.println("attribute: " + attributes.getValue(i));
        }
    }
}

【讨论】:

  • 谢谢。但是我们不想将文件加载到内存中,因为我们将接收大文件。并且大量。很抱歉没有事先提及要求。
  • @Jenny 听起来您需要 StAX 解析器(用于 Xml 处理的 STreaming Api)。查看woodstox.codehaus.org
  • 现在我遇到了不同的问题。如果我的 xml 有 3 个节点,例如姓名、电子邮件和电话,那么我可以将它们保存到 pojo 类中。但是现在的情况是我们不知道传入的 xml 中有哪些所有数据。我该如何存储它?
猜你喜欢
  • 2013-07-05
  • 1970-01-01
  • 1970-01-01
  • 2020-02-24
  • 1970-01-01
  • 1970-01-01
  • 2016-08-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多