如何用Java向XML Schema/XSD文件中添加import语句?
问题:Java向XSD文件添加import语句报错解决办法
用户想要用Java向现有Schema/XSD文件中添加import语句,执行代码时触发错误:
org.w3c.dom.DOMException: HIERARCHY_REQUEST_ERR: An attempt was made to insert a node where it is not permitted.
原有Schema内容
<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> <!-- ommitted rest of the content--> </xs:schema>
期望添加import后的Schema
<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> <xs:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="myownLocation"/> <!-- ommitted rest of the content--> </xs:schema>
用户原代码
Document doc = DocumentBuilderFactory .newInstance() .newDocumentBuilder() .parse(new FileInputStream("testXSD.xml")); Element blobKey_E = doc.createElement("xs:import"); blobKey_E.setAttribute("namespace", "http://www.w3.org/2000/09/kk#"); blobKey_E.setAttribute("schemaLocation", "myownLocation"); doc.appendChild(blobKey_E); TransformerFactory .newInstance() .newTransformer() .transform(new DOMSource(doc.getDocumentElement()), new StreamResult(System.out));
错误原因
你犯了两个核心错误:
- 直接把
<xs:import>节点添加到Document对象下——DOM规范中,Document的直接子节点只能是文档类型声明、处理指令、注释或根元素,<xs:import>必须作为根元素<xs:schema>的子节点插入。 - 创建带命名空间的元素时用了
createElement("xs:import")——这种方式不会正确关联XML命名空间,导致元素结构不符合XSD规范。
修正后的代码
import org.w3c.dom.Document; import org.w3c.dom.Element; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import java.io.FileInputStream; public class XsdImportAdder { public static void main(String[] args) throws Exception { // 初始化解析器,启用命名空间支持 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.parse(new FileInputStream("testXSD.xml")); // 获取XSD的根元素<xs:schema> Element rootSchema = doc.getDocumentElement(); // 创建带正确命名空间的<xs:import>元素 String xsNamespace = "http://www.w3.org/2001/XMLSchema"; Element importElement = doc.createElementNS(xsNamespace, "xs:import"); importElement.setAttribute("namespace", "http://www.w3.org/XML/1998/namespace"); importElement.setAttribute("schemaLocation", "myownLocation"); // 将import元素插入到根元素的最前面(符合XSD规范中import前置的习惯) rootSchema.insertBefore(importElement, rootSchema.getFirstChild()); // 输出修改后的XSD内容 Transformer transformer = TransformerFactory.newInstance().newTransformer(); transformer.transform(new DOMSource(doc), new StreamResult(System.out)); } }
关键修正点
- 启用命名空间支持:
factory.setNamespaceAware(true),确保解析和生成的XML正确处理命名空间。 - 使用
createElementNS创建元素:指定XSD的命名空间URI,保证<xs:import>元素的合法性。 - 插入位置修正:将元素添加到
<xs:schema>节点下,而非Document节点。 - 位置控制:用
insertBefore把import语句放在根元素最前面,符合XSD的编写规范;如果需要追加到末尾,改用rootSchema.appendChild(importElement)即可。
内容的提问来源于stack exchange,提问作者kantesh
相关产品推荐
相关产品推荐

