0

我正在尝试创建一个将拆分所选 XML 文件的 java 程序。

XML 文件数据示例:

<EmployeeDetails>
<Employee>
<FirstName>Ben</FirstName>
</Employee>
<Employee>
<FirstName>George</FirstName>
</Employee>
<Employee>
<FirstName>Cling</FirstName>
</Employee>
<EmployeeDetails>

依此类推,我有这个 250mb 的 XML 文件,它总是很痛苦地打开它外部程序并手动拆分它以便能够与其他程序一起读取(并非所有笔记本电脑/台式机都可以打开这么大的文件)。所以我决定创建一个具有此功能的 Java 程序: - 选择 XML 文件(已经完成) - 根据标签数量分割文件,例如。(当前文件有 100k 个标签我会询问程序用户他是如何员工的/她想要拆分的文件。例如(每个文件 10k)-拆分文件(已经完成)

我只是想就如何完成第二项任务寻求帮助,已经在 3-4 天内检查我怎么可能做到这一点,或者它是否可行(在我看来当然是这样)。

任何回应将不胜感激。

干杯,格林。

4

2 回答 2

2

假设文档 R 的根元素具有大量名为 X 的子元素的平面结构,则以下 XSLT 2.0 转换将每隔 N 个 X 元素拆分文件。

<t:transform xmlns:t="http://www.w3.org/1999/XSL/Transform"
  version="2.0">
  <t:param name="N" select="100"/>
  <t:template match="/*">
    <t:for-each-group select="X" 
                      group-adjacent="(position()-1) idiv $N">
      <t:result-document href="{position()}.xml">
        <R>
          <t:copy-of select="current-group()"/>
        </R>
      </t:result-document>
   </t:for-each-group>
  </t:template>
</t:transform> 

如果您想在流模式下运行它(而不在内存中构建源代码树),那么 (a) add<xsl:mode streamable="yes"/>和 (b) 使用 XSLT 3.0 处理器(Saxon-EE 或 Exselt)运行它。

于 2016-06-20T10:14:21.880 回答
0

一个简单的解决方案是有序的。如果 XML 始终具有所示的那些换行符,则不需要 XML 处理。

Path originalPath = Paths.get("... .xml");
try (BufferedReader in = Files.newBufferedReader(originalPath, StandardCharsets.UTF_8)) {
    String line = in.readLine(); // Skip header line(s)

    line = in.readLine();
    for (int fileno; line != null && !line.contains("</EmployeeDetails>"); ++fileno) {
        Path partPath = Paths.get("...-" + fileno + ".xml");
        try (PrintWriter out = new PrintWriter(Files.newBufferedWriter(partPath,
                StandardCharsets.UTF_8))) {
            int counter = 0;
            out.println("<EmployeeDetails>"); // Write header.
            do {
                out.println(line);
                if (line.contains("</Employee>") {
                    ++counter;
                }
                line = in.readLine();
            } while (line != null && !line.contains("</EmployeeDetails>")
                    && counter < 1000);
            out.println("</EmployeeDetails>");
        }
    }
}
于 2016-06-20T10:43:56.713 回答