如标题所示,我正在尝试使用for循环将元素添加到xml文档中。我有一个ArrayList字符串叫names,我想遍历,并为每个名称创建一个<user>元素与属性name,并与孩子<record>具有的属性id,time,date,和project。
ArrayList
names
<user>
name
<record>
id
time
date
project
不幸的是,如果您在下面的代码中向下滚动到该createDoc()方法,当我尝试调用时doc.appendChild(user),会出现以下错误:
createDoc()
doc.appendChild(user)
Exception in thread "main" org.w3c.dom.DOMException: HIERARCHY_REQUEST_ERR: An attempt was made to insert a node where it is not permitted. at org.apache.xerces.dom.CoreDocumentImpl.insertBefore(Unknown Source) at org.apache.xerces.dom.NodeImpl.appendChild(Unknown Source) at test.XMLwriter.createDoc(XMLwriter.java:131) at test.XMLwriter.<init>(XMLwriter.java:116) at test.TestRunner.main(TestRunner.java:33)
我看了几个关于stackoverflow的具有相同错误的问题,但是它们似乎都是在与我的情况完全不同的情况下发生的。我最好的猜测是,该错误与以下事实有关:我试图在同一层次级别上创建太多父元素。
这是代码:
public class XMLwriter { private ArrayList<String> names; private Document doc; private Random rand; private ArrayList<Element> users; public XMLwriter() throws ParserConfigurationException, TransformerException{ DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); doc = docBuilder.newDocument(); rand = new Random(); users = new ArrayList<Element>(); names = new ArrayList<String>(); names.add("Ralph Wiggum");names.add("Mr. Hanky");names.add("Bulbasaur"); names.add("Tyroil Smoochie Wallace");names.add("Scooby Doo");names.add("Neville Longbottom"); names.add("Jabba the Hutt");names.add("Silky Johnson");names.add("Master Chief"); names.add("Frodo Baggins");names.add("Clayton Bigsby");names.add("John Snow"); names.add("Eric Cartman");names.add("Leoz Maxwell Jilliumz");names.add("Aslan"); createDoc(); generateFile(); } public void createDoc(){ for(int k = 0; k < names.size(); k++) { users.add(doc.createElement("user")); } for (int x = 0; x < names.size(); x++){ //create the elements Element record = doc.createElement("record"); users.get(x).appendChild(record); doc.appendChild(users.get(x));//The line that is throwing the error //create the attributes Attr name = doc.createAttribute("name"); Attr date = doc.createAttribute("date"); Attr project = doc.createAttribute("project"); Attr time = doc.createAttribute("time"); Attr id = doc.createAttribute("id"); //give all of the attributes values name.setValue(names.get(x)); date.setValue(new Date().toString()); project.setValue("Project" + (rand.nextDouble() * 1000)); time.setValue("" + rand.nextInt(10)); id.setValue("" + (rand.nextDouble() * 10000)); //assign the attributes to the elements users.get(x).setAttributeNode(name); record.setAttributeNode(date); record.setAttributeNode(project); record.setAttributeNode(time); record.setAttributeNode(id); } } public void generateFile() throws TransformerException{ TransformerFactory transformerFactory = TransformerFactory.newInstance(); Transformer transformer = transformerFactory.newTransformer(); DOMSource source = new DOMSource(doc); StreamResult result = new StreamResult(new File("C:\\Users\\sweidenkopf\\workspace\\test\\testxml.xml")); // Output to console for testing // StreamResult result = new StreamResult(System.out); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); transformer.transform(source, result); }
}
我发现了这个问题的答案。方法如下:
我创建了另一个层次结构层,<userList>每次迭代for循环时,我都会使新创建<user>的子层为<userList>。
<userList>
最后,超出了for循环的范围,我<userList>将xml文档作为整个子文档。
这是那些有兴趣的新代码。您可以阅读createDoc()方法中的注释,以帮助弄清楚我在上面解释的内容:
public class XMLwriter { private ArrayList<String> names; private Document doc; private Random rand; private ArrayList<Element> users; public XMLwriter() throws ParserConfigurationException, TransformerException{ DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); doc = docBuilder.newDocument(); rand = new Random(); users = new ArrayList<Element>(); names = new ArrayList<String>(); names.add("Ralph Wiggum");names.add("Mr. Hanky");names.add("Bulbasaur"); names.add("Tyroil Smoochie Wallace");names.add("Scooby Doo");names.add("Neville Longbottom"); names.add("Jabba the Hutt");names.add("Silky Johnson");names.add("Master Chief"); names.add("Frodo Baggins");names.add("Clayton Bigsby");names.add("John Snow"); names.add("Eric Cartman");names.add("Leoz Maxwell Jilliumz");names.add("Aslan"); createDoc(); generateFile(); } public void createDoc(){ Element userList = doc.createElement("userList");//here, I create a new, over-arching element. for(int k = 0; k < names.size(); k++) { users.add(doc.createElement("user")); } for (int x = 0; x < 2; x++){ //create the elements Element record = doc.createElement("record"); users.get(x).appendChild(record); userList.appendChild(users.get(x));//I make each of the <user> elements a child of the over-arching element //The line that was throwing the error //create the attributes Attr name = doc.createAttribute("name"); Attr date = doc.createAttribute("date"); Attr project = doc.createAttribute("project"); Attr time = doc.createAttribute("time"); Attr id = doc.createAttribute("id"); //give all of the attributes values name.setValue(names.get(x)); date.setValue(new Date().toString()); project.setValue("Project" + (rand.nextDouble() * 1000)); time.setValue("" + rand.nextInt(10)); id.setValue("" + (rand.nextDouble() * 10000)); //assign the attributes to the elements users.get(x).setAttributeNode(name); record.setAttributeNode(date); record.setAttributeNode(project); record.setAttributeNode(time); record.setAttributeNode(id); } doc.appendChild(userList);//note how I append this child outside of the for loop } public void generateFile() throws TransformerException{ TransformerFactory transformerFactory = TransformerFactory.newInstance(); Transformer transformer = transformerFactory.newTransformer(); DOMSource source = new DOMSource(doc); StreamResult result = new StreamResult(new File("C:\\Users\\sweidenkopf\\workspace\\test\\testxml.xml")); // Output to console for testing // StreamResult result = new StreamResult(System.out); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); transformer.transform(source, result); } }