Java XML 创建

标签 java xml

我正在尝试从 XML 文档获取属性 ID (fileID),以用作 XML 拆分的文件名。拆分工作正常,我只需要提取 fileID 用作名称即可。

[已编辑] 我现在可以读取该属性,但它不会创建最后一个 xml 文件。因此,在我的示例中,它创建了具有正确名称的前 2 个文件,但未创建最后一个文件 ID“000154OP.XML”。有人可以帮忙吗?

这是我的 xml 文档

<root>
 <envelope fileID="000152OP.XML">
   <record id="850">
   </record>
</envelope>
<envelope fileID="000153OP.XML">
  <record id="850">
  </record>
</envelope>
<envelope fileID="000154OP.XML">
  <record id="850">
  </record>
</envelope>
</root>

这是我的 Java 代码

    public static void splitXMLFile (String file) throws Exception {         
    String[] temp;
    String[] temp2;
    String[] temp3;
    String[] temp4;
    String[] temp5;
    String[] temp6;
    File input = new File(file);         
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();         
    Document doc = dbf.newDocumentBuilder().parse(input);
    XPath xpath = XPathFactory.newInstance().newXPath();          
    NodeList nodes = (NodeList) xpath.evaluate("//root/envelope", doc, XPathConstants.NODESET);          
    int itemsPerFile = 1;         

    Node staff = doc.getElementsByTagName("envelope").item(0);

    NamedNodeMap attr = staff.getAttributes();
    Node nodeAttr = attr.getNamedItem("fileID");
    String node = nodeAttr.toString();
    temp = node.split("=");
    temp2 = temp[1].split("^\"");
    temp3 = temp2[1].split("\\.");

    Document currentDoc = dbf.newDocumentBuilder().newDocument();         
    Node rootNode = currentDoc.createElement("root");   
    File currentFile = new File("C:\\XMLFiles\\" + temp3[0]+ ".xml"); 

    for (int i=1; i <= nodes.getLength(); i++) {             
        Node imported = currentDoc.importNode(nodes.item(i-1), true);             
        rootNode.appendChild(imported); 

        Node staff2 = doc.getElementsByTagName("envelope").item(i);
        NamedNodeMap attr2 = staff2.getAttributes();
        Node nodeAttr2 = attr2.getNamedItem("fileID");
        String node2 = nodeAttr2.toString();
        temp4 = node2.split("=");
        temp5 = temp4[1].split("^\"");
        temp6 = temp5[1].split("\\.");

        if (i % itemsPerFile == 0) { 

            writeToFile(rootNode, currentFile);                  
            rootNode = currentDoc.createElement("root");    
            currentFile = new File("C:\\XMLFiles\\" + temp6[0]+".xml");


        }         
    }          
    writeToFile(rootNode, currentFile);     
}    

 private static void writeToFile(Node node, File file) throws Exception {         
     Transformer transformer = TransformerFactory.newInstance().newTransformer();         
     transformer.transform(new DOMSource(node), new StreamResult(new FileWriter(file)));     
 } 

最佳答案

您的代码中有很多重复,但我有一个解决方案可以删除很多重复。我知道有不太复杂的解决方案(例如,我认为不需要 if (i % itemsPerFile == 0) 逻辑,但我不知道您的所有要求,所以我将其保留。

您遇到的主要问题是用错误的数据覆盖最后一个文件,而且您的循环逻辑是重复的。我遵循的一个好的经验法则是,每当我认为我可能需要重复代码时,就会出现问题。你的逻辑是考虑第一个 <envelope>分别分配给剩余的<envelope>元素,而它们应该被视为3个一组。那么你的逻辑只需要依次对每个元素应用相同的搜索、拆分、匹配、导入等。

复杂的是,你的输入XML文件具有相同的 <record id="850">对于每个 <envelope> 。我把我的改为850 , 851852 。运行原始代码,生成 3 个文件,000152OP.xml , 000153OP.xml000154OP.xml ,但第一个包含 851记录。所以我立刻就知道循环逻辑是不正确的。

下面详细介绍了一个更简单的解决方案,它将输入 XML 文件作为参数,在同一目录中生成 3 个输出文件(为了简单起见,我删除了 C:\ 硬编码),每个文件都有正确的 <record>元素。

import java.io.*;
import java.util.Random;
import org.w3c.dom.*;
import javax.xml.parsers.*;
import javax.xml.xpath.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;

public class SplitXML {
    public static void main(String[] args) throws Exception {
        File input = new File(args[0]);
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        Document doc = dbf.newDocumentBuilder().parse(input);
        XPath xpath = XPathFactory.newInstance().newXPath();
        NodeList nodes = (NodeList) xpath.evaluate("//root/envelope", doc, XPathConstants.NODESET);
        int itemsPerFile = 1;

        Document currentDoc = dbf.newDocumentBuilder().newDocument();

        for (int i=0; i < nodes.getLength(); i++) {
            Node rootNode = currentDoc.createElement("root");

            Node imported = currentDoc.importNode(nodes.item(i), true);
            rootNode.appendChild(imported);

            Node staff = doc.getElementsByTagName("envelope").item(i);
            NamedNodeMap attr = staff.getAttributes();
            Node nodeAttr = attr.getNamedItem("fileID");
            String filename = nodeAttr.getNodeValue();
            String[] fileParts = filename.split("\\.");

            if (i % itemsPerFile == 0) {
                File currentFile = new File(fileParts[0] + "." + fileParts[1].toLowerCase());
                writeToFile(rootNode, currentFile);
            }
        }
    }

    private static void writeToFile(Node node, File file) throws Exception {
        Transformer transformer = TransformerFactory.newInstance().newTransformer();
        transformer.transform(new DOMSource(node), new StreamResult(new FileWriter(file)));
    }
}

您应该阅读 NodeString::split因为在 native 方法已经存在的情况下存在不必要的额外代码(例如 [Node::getNodeValue()][3] )。

编辑:创建 1000 <envelope> 的来源我用来测试上述代码的元素:

import java.io.*;

public class CreateXML {
    public static void main(String[] args) throws Exception {
        FileWriter fstream = new FileWriter(new File("split.xml"));
        BufferedWriter out = new BufferedWriter(fstream);
        out.write("<root>");
        for (int i = 0; i < 1000; i++) {
            out.write("<envelope fileID=\"000" + i +"P.XML\"><record id=\"" + i + "\"></record></envelope>\n");
        }
        out.write("</root>");
        out.close();
    }
}

我跑了java CreateXML创建输入文件 split.xml然后java SplitXML split.xml创建 1000 个文件。

关于Java XML 创建,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6343295/

相关文章:

java - 如何将我得到的 JSON 文件转换为数字,以便我可以在 Android 上操作它们

Android - 从形状 xml 引用的 ColorStateList xml 的问题

html - 获取 sibling 之后的 xpath 以使用具有其值的模板

java - 使用 java 在时间轴中查找缺失的日期范围

java - 如何将列表项转换为 int/double

Java GUI - MouseListener 和 ActionListener 可以在同一个类中吗?

java - 在 JBoss 上运行 Spring Boot 应用程序 - 忽略端点的问题

java - JAXB - 解码 XML 异常

sql - SQL如何修改XML中属性的首位?

java - 值在模式方面不是有效的