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

Java 如何从基本xml开始创建一个巨大的xml(>;2GB),java,xml,sax,stax,Java,Xml,Sax,Stax,我需要开发一些功能来进行一些负载测试。该功能的目标是基于现有xml创建一个xml(大小>2GB)。xml定义了文档和(文档的)集合。每个文档和集合都包含许多定义文档/集合的标记。基本xml大约为100KB。它包含2个文档和一个集合。基于这个xml,我想创建一个新的xml。在生成的xml中,应该多次复制集合和文档(最多100.000次) 一个小的计算表明,生成的xml的大小可能大于2GB。恐怕这不包括DOM解析 基本xml具有以下格式(这不是结果xml,但其结构类似): ... ... ...

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

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

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


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

  • 文集
  • 保存结果xml:结果xml是基本xml+以xml形式复制的集合
  • 使用生成的xml并复制文档
  • 由于结果xml将是巨大的(2GB),我使用了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()));
    }
    
    public静态最终字符串LEGAL\u ENTITY\u NAMESPACE=”http://some/name/space";
    公共void填充(XMLEventWriter编写器,int缩进){
    地址=AddressBuilder.builder().build();
    QName addressQName=新的QName(法律实体名称空间,“地址”);
    setDefaultNamespace(法律实体名称空间);
    createStartElement(writer、addressQName、Optional.empty()、Optional.empty()、indent);
    createElement(writer,新的QName(LEGAL_ENTITY_NAMESPACE,“street”),address.getStreet(),缩进+1);
    createElement(writer,新的QName(合法的实体名称空间,“houseNumber”),address.getHouseNumber(),缩进+1);
    createElement(writer,新的QName(LEGAL_ENTITY_名称空间,“boxNumber”),address.getBoxNumber(),indent+1);
    createElement(writer,新的QName(LEGAL_ENTITY_NAMESPACE,“city”),address.getCity(),缩进+1);
    createElement(writer,新QName(LEGAL_ENTITY_NAMESPACE,“zipcode”),address.getZipcode(),缩进+1);
    createEndElement(编写器、地址QName、缩进);
    }
    public void createStartElement(XMLEventWriter编写器、QName元素、可选属性、,
    可选名称空间,int缩进){
    附加标签(书写者、缩进);
    add(eventFactory.createStartElement(元素、属性、orElse(null)、nameSpaces.orElse(null));
    }
    public void createElement(XMLEventWriter编写器、QName元素、字符串值、int缩进){
    附加标签(书写者、缩进);
    add(eventFactory.createStartElement(element,null,null));
    add(eventFactory.createCharacters(value));
    add(eventFactory.createEndElement(“,”,element.getLocalPart());
    }
    public void createEndElement(XMLEventWriter编写器、QName元素、int缩进){
    附加标签(书写者、缩进);
    add(eventFactory.createEndElement(“,”,element.getLocalPart());
    }
    
    上面的代码是如何将集合添加到新xml的示例。当然,还有更多的代码。这个很好用。我现在得到的结果是一个基于基本xml的xml,具有大量集合

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

    总结:

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

  • 由于生成的xml的大小,选择stax解析可以吗
  • 考虑到最终结果将是一个巨大的xml,我如何用xml复制完整的文档标记 请考虑将XML文件转换为其他XML、HTML甚至文本文件的专用声明性语言。使用这种方法,您可以简单地复制现有XML中所需的元素,并避免使用DOM方法在Java中手动重建树

    因为XSLT是自己的语言,所以它是可移植的。下面是一个<>代码> javax .xM*/COML>实现,但是考虑java库中可用的命令行工具,并可以帮助大文件输出。具体地说,XSLT运行标识转换以原样复制文档,然后在集合中复制其子集合以进行所需的迭代次数(这里是5次)。看他用撒克逊人

    XSLT1.0(另存为.xsl文件,一个特殊的.xml文件,在Java中引用)

    <
    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()));
    }
    
    <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>
    
    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);
        }
    }
    
    java org.apache.xalan.xslt.Process -IN source.xml -XSL script.xsl -OUT output.xml
    
    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