gpt4 book ai didi

java - 如何从基本 xml 开始创建一个巨大的 xml (> 2GB)

转载 作者:行者123 更新时间:2023-11-30 05:30:56 25 4
gpt4 key购买 nike

我需要开发一些功能来进行一些负载测试。该功能的目标是基于现有 xml 创建 xml(大小 > 2 GB)。 xml 定义文档和(文档的)集合。每个文档和集合都包含许多定义文档/集合的标签。基本 xml 大约为 100 kb。它包含 2 个文档和 1 个集合。基于这个 xml,我想创建一个新的 xml。在生成的 xml 中,集合和文档应复制多次(最多 100.000 次)。

小规模计算表明,生成的 xml 的大小可能大于 2 GB。恐怕这不包括 DOM 解析。

基础 xml 具有以下格式(这不是结果 xml,但其结构类似):

<request attribute1="xxx" attribute2="yyy">
<element1>...</element1>
<element2>...</element2>
<documents>
<document>
<documentReference></documentReference>
<documentElement1></documentElement1>
<documentElement2></documentElement2>
<documentElement3></documentElement3>
... (document contains a lot of information (element tags))
</document>
<document>
<documentReference></documentReference>
<documentElement1></documentElement1>
<documentElement2></documentElement2>
<documentElement3></documentElement3>
... (document contains a lot of information (element tags))
</document>
</documents>
<collections>
<collection>
<collectionReference></collectionReference>
<collectionElement1></collectionElement1>
<collectionElement2></collectionElement2>
<collectionElement3></collectionElement3>
<documents>
<document>
<documentReference></documentReference>
<someTagDefiningTheDocument1>...</someTagDefiningTheDocument1>
<someTagDefiningTheDocument2>...</someTagDefiningTheDocument2>
</document>
</documents>
</collection>
</collections>
</request>

在上面的xml中,集合和文档需要复制多次(最多100.000次)。副本中唯一需要更新的值是引用。文档标签包含大量数据,但集合标签相当小。我的想法是分两步完成:

  1. 复制集合
  2. 保存生成的 xml:生成的 xml 是基本 xml + xml 中复制的集合
  3. 使用生成的 xml 并复制文档

由于结果 xml 会很大(2 GB),我使用 stax 解析器来复制集合任意多次。这项工作是可行的。最终结果是一个 xml,包含给定数量的集合并保存在给定目录中。结果很好。这样步骤1和2就完成了。以下是我如何使用 stax 解析器添加集合元素的示例:

public static final String LEGAL_ENTITY_NAMESPACE = "http://some/name/space";

public void populate(XMLEventWriter writer, int indent) {
Address address = AddressBuilder.builder().build();
QName addressQName = new QName(LEGAL_ENTITY_NAMESPACE, "address");
writer.setDefaultNamespace(LEGAL_ENTITY_NAMESPACE);
createStartElement(writer, addressQName, Optional.empty(), Optional.empty(), indent);
createElement(writer, new QName(LEGAL_ENTITY_NAMESPACE, "street"), address.getStreet(), indent + 1);
createElement(writer, new QName(LEGAL_ENTITY_NAMESPACE, "houseNumber"), address.getHouseNumber(), indent + 1);
createElement(writer, new QName(LEGAL_ENTITY_NAMESPACE, "boxNumber"), address.getBoxNumber(), indent + 1);
populatorHelper.createElement(writer, new QName(LEGAL_ENTITY_NAMESPACE, "city"), address.getCity(), indent + 1);
createElement(writer, new QName(LEGAL_ENTITY_NAMESPACE, "zipcode"), address.getZipcode(), indent + 1);
createEndElement(writer, addressQName, indent);
}

public void createStartElement(XMLEventWriter writer, QName element, Optional<Iterator<Attribute>> attributes,
Optional<Iterator<Namespace>> nameSpaces, int indent) {
addEndAndTabs(writer, indent);
writer.add(eventFactory.createStartElement(element, attributes.orElse(null), nameSpaces.orElse(null)));
}

public void createElement(XMLEventWriter writer, QName element, String value, int indent) {
addEndAndTabs(writer, indent);
writer.add(eventFactory.createStartElement(element, null, null));
writer.add(eventFactory.createCharacters(value));
writer.add(eventFactory.createEndElement("", "", element.getLocalPart()));
}

public void createEndElement(XMLEventWriter writer, QName element, int indent) {
addEndAndTabs(writer, indent);
writer.add(eventFactory.createEndElement("", "", element.getLocalPart()));
}

上面的代码是如何将集合添加到新 xml 的示例。当然,还涉及更多代码。这很好用。我现在得到的结果是一个 xml,基于基础 xml,具有大量集合。

我仍然需要执行第三步:复制文档(及其所有内容)并更新文档引用。但是,使用 stax 我需要创建每个标签。由于xml中的文档超过1000行(有大量描述文档的信息),这是不可行的。所以我想知道是否可以在生成的 xml 中复制完整的文档标签(及其所有内容)。

摘要:

  • 基础 xml(上面发布的 xml)用于生成 xml。
  • 使用 stax 解析器,根据上述基本 xml 创建结果 xml。结果 xml 已包含复制的集合(上面的示例代码)。
  • 生成的 xml(包含复制的集合)保存在目录中 (xml = 250 MB)。
  • 下一步:复制文档。请记住:文档标签包含大量数据。最终结果将是 2 GB 的 xml。
  • 最终结果应该是一个 xml,基于基本 xml(上面发布的),包含大量文档和集合。

问题:

  1. 由于生成的 xml 的大小,选择 stax 解析是否合适?
  2. 考虑到最终结果将是一个巨大的 xml,如何复制 xml 中的完整文档标签?

最佳答案

考虑XSLT ,一种特殊用途的声明性语言,用于将 XML 文件转换为其他 XML、HTML,甚至文本文件。通过这种方法,您可以简单地复制现有 XML 中所需的元素,并避免使用 DOM 方法在 Java 中手动重建树。

因为 XSLT 是它自己的语言,所以它是可移植的。下面是一个 javax.xml 实现,但请考虑 XalanSaxon Java 库中提供了命令行工具,可以帮助处理大文件输出。具体来说,XSLT 运行恒等转换以按原样复制文档,然后在集合 中复制其子集合 所需的迭代次数(此处为 5)。请参阅XSLT Demo使用 Saxon HE。

XSLT 1.0 (另存为.xsl文件,一种特殊的.xml文件,以便在Java中引用)

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>

<!-- IDENTITY TRANSFORM -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>

<xsl:template match="collections">
<xsl:copy>
<xsl:apply-templates select="collection" mode="iter">
<xsl:with-param name="pCount" select="5"/> <!-- ADJUST NUMBER OF ITERATIONS -->
</xsl:apply-templates>
</xsl:copy>
</xsl:template>

<xsl:template match="collection" mode="iter">
<xsl:param name="pCount"/>
<xsl:if test="$pCount > 0">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
<xsl:apply-templates select="." mode="iter">
<xsl:with-param name="pCount" select="$pCount -1"/>
</xsl:apply-templates>
</xsl:if>
</xsl:template>

</xsl:stylesheet>

Java

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import javax.xml.transform.*;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerException;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.transform.OutputKeys;

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;

import org.w3c.dom.Document;
import org.xml.sax.SAXException;


public class XSLTransform_JAVA {

public static void main(String[] args) throws IOException, URISyntaxException,
SAXException, ParserConfigurationException,
TransformerException {

// Load XML and XSL Document
String inputXML = "/path/to/Input.xml";
String xslFile = "/path/to/XSLT_Script.xsl";
String outputXML = "/path/to/Output.xml";

Source xslt = new StreamSource(new File(xslFile));
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.parse (new File(inputXML));

// XSLT Transformation with pretty print
TransformerFactory prettyPrint = TransformerFactory.newInstance();
Transformer transformer = prettyPrint.newTransformer(xslt);

transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
transformer.setOutputProperty(OutputKeys.STANDALONE, "yes");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");

// Output Result to File
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File(outputXML));
transformer.transform(source, result);
}
}
<小时/>

Xalan command line

java org.apache.xalan.xslt.Process -IN source.xml -XSL script.xsl -OUT output.xml

Saxon command line

java net.sf.saxon.Transform -s:source.xml -xsl:script.xsl -o:output.xml

java -jar dir/saxon9he.jar -s:source.xml -xsl:script.xsl -o:output.xml

Other XSLT tools...

关于java - 如何从基本 xml 开始创建一个巨大的 xml (> 2GB),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57575252/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com