XML - Java中的XPath DOM解析器

时间:2018-04-05 21:01:51

标签: java xml dom xpath

我有以下XML:

<docs>
<doc>
    <person>
        <name>John Doe</name>
        <description>
            <age>23</age>
            <alias>M C</alias>
        </description>
        <description>
            <age>24</age>
            <alias>John</alias>
        </description>
    </person>
<doc>
<doc>
    <person>
        <name>John Doe</name>
        <description>
            <age>24</age>
            <alias>Steve</alias>
        </description>
    </person>
<doc>
</docs>

我无法控制xml。我得到的只是这样的xml文档和元素的xpath。我编写了一个java程序来读取数据并将其转换为Json对象。我正在使用xPath和dom解析器,因为我们得到xPath for xml,我想我会利用它,因为xPath将来可能会改变。所以我对属性文件中的所有元素都有xPath,所以如果有更改,我将在程序中进行最小的更改。不幸的是程序应该不区分大小写,因此我使用translate(xPath)来处理它。我有以下课程

public class Person {
  private List<String> name;
  private List<String> age;
  private List<String> alias;
  //getter and setter
}

问题是拥有多个doc节点,每个节点都可以有多个age和alias元素。之前它不是必需的,所以我使用XPath来获取文本,但现在我不能使用它,因为// person / description的xPath将返回3个节点,2个来自第一个doc,另一个来自另一个doc。问题是我需要区分描述标签,以确定它是来自第一个文档还是来自另一个文档。所以最终的Json看起来像

{
  "docs":
  {
    "doc":
    [
      {
        "description":
         [
           {
             "age": 23,
             "alias": "M C"
           },
           {
             "age": 24,
             "alias": "John"
           }
         ]
       },
       {
          "description":
           [
            {
              "age": 24,
              "alias": "Steve"
            }
           ]
         }
    ]
  }
 }

所以我能想到的是编译xPath表达式 - // docs / doc,此时我将有2个节点并获取子节点并通过获取子节点进行循环并执行类似if

element.getTagName().equalsIgnoreCase("age") 

然后添加到年龄列表,然后像列表一样,所以我最终会有

docs[[[23, "M C"],[24, "John"]],[[24, "Steve"]]]

有更好的想法吗?

1 个答案:

答案 0 :(得分:0)

XPath的替代方案是Java JSON library。该库具有使用XML和生成JSON的功能。要完成此转换,请使用以下命令:

public class Main {

    private static int SPACES_PER_INDENT = 4;

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

        try {
            // Citation: https://stackoverflow.com/questions/1823264/quickest-way-to-convert-xml-to-json-in-java
            URI file = Main.class.getClassLoader().getResource("docs.xml").toURI();
            String xmlContents = readFromInputStream(file);
            JSONObject jsonContents = XML.toJSONObject(xmlContents);
            String jsonString = jsonContents.toString(SPACES_PER_INDENT);
            System.out.println(jsonString);
        } 
        catch (JSONException e) {
            e.printStackTrace();
        }
    }

    private static String readFromInputStream(URI uri) throws IOException {
        // Citation: http://www.baeldung.com/reading-file-in-java
        Path path = Paths.get(uri);
        StringBuilder data = new StringBuilder();

        Stream<String> lines = Files.lines(path);
        lines.forEach(line -> data.append(line).append("\n"));
        lines.close();

        return data.toString();
    }
}

类路径中存在的docs.xml内容如下(请注意,我将问题中的<doc>...<doc>标记更改为<doc>...</doc>):

<docs>
    <doc>
        <person>
            <name>John Doe</name>
            <description>
                <age>23</age>
                <alias>M C</alias>
            </description>
            <description>
                <age>24</age>
                <alias>John</alias>
            </description>
        </person>
    </doc>
    <doc>
        <person>
            <name>John Doe</name>
            <description>
                <age>24</age>
                <alias>Steve</alias>
            </description>
        </person>
    </doc>
</docs>

这个项目的pom.xml是:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.stackoverflow.albanoj2</groupId>
    <artifactId>XmlToJson</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.json</groupId>
            <artifactId>json</artifactId>
            <version>20180130</version>
        </dependency>
    </dependencies>
</project>

结果输出为:

{"docs": {"doc": [
    {"person": {
        "name": "John Doe",
        "description": [
            {
                "alias": "M C",
                "age": 23
            },
            {
                "alias": "John",
                "age": 24
            }
        ]
    }},
    {"person": {
        "name": "John Doe",
        "description": {
            "alias": "Steve",
            "age": 24
        }
    }}
]}}

如果更容易阅读,此解决方案的源代码包含在以下存储库中:https://github.com/albanoj2/XmlToJsonDocTranslation。请注意,此答案的大部分内容源自Quickest way to convert XML to JSON in Java,但已根据此问题的特定需求进行了定制(例如从文件中读取XML)。