在 Java DOM 中创建以命名空间为前缀的 XML 节点
Posted
技术标签:
【中文标题】在 Java DOM 中创建以命名空间为前缀的 XML 节点【英文标题】:Creating namespace prefixed XML nodes in Java DOM 【发布时间】:2015-04-14 07:10:46 【问题描述】:我正在通过 Java 创建几个 XML 文件,到目前为止一切正常,但现在我在尝试创建具有命名空间前缀节点的文件时遇到了问题,即使用重构的 <tns:node> ... </tns:node>
之类的东西我的代码版本已经适用于没有命名空间的普通 xml 文件。
抛出的错误是:
org.w3c.dom.DOMException: INVALID_CHARACTER_ERR: Ungültiges XML-Zeichen angegeben.
对不起那里的德国人,上面写着“指定的 XML 符号无效”。
发生错误的代码行:
Element mainRootElement = doc.createElement("tns:cmds xmlns:tns=\"http://abc.de/x/y/z\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://abc.de/x/y/z xyzschema.xsd\"");
为了消除错误导致转义相当长的字符串或其他内容的可能性,我也尝试使用Element mainRootElement = doc.createElement("tns:cmds");
,但是,这会导致相同的错误。
这就是为什么我认为它与命名空间声明有关,即 :
曾经这样做,因为这是我能想到的字符串中唯一的“无效”字符。
谁能确认这是问题的根源?如果是这样,是否有一个简单的解决方案? Java DOM 可以使用命名空间标签吗?
编辑:整个方法供参考
private void generateScriptXML()
DocumentBuilderFactory icFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder icBuilder;
try
icBuilder = icFactory.newDocumentBuilder();
Document doc = icBuilder.newDocument();
Element mainRootElement = doc.createElement("tns:cmds xmlns:tns=\"http://abc.de/x/y/z\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://abc.de/x/y/z xyzschema.xsd\"");
doc.appendChild(mainRootElement);
mainRootElement.appendChild(getAttributes(doc,"xxx", "yyy", "zzz"));
mainRootElement.appendChild(getAttributes(doc,"aaa", "bbb", "ccc"));
mainRootElement.appendChild(getAttributes(doc,"ddd", "eee", "fff"));
...
...
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
DOMSource source = new DOMSource(doc);
StreamResult streamResult = new StreamResult(new File(vfsPath));
transformer.transform(source, streamResult);
catch (Exception e)
e.printStackTrace();
【问题讨论】:
另见***.com/questions/11133754/… 【参考方案1】:方法不对,试试*NS变体:
Element mainRootElement = doc.createElementNS(
"http://abc.de/x/y/z", // namespace
"tns:cmds" // node name including prefix
);
第一个参数是命名空间,第二个参数是包含前缀/别名的节点名。如果需要,将为命名空间自动添加命名空间定义。也可以将它们设置为属性。
原始源中的命名空间是http://abc.de/x/y/z
。使用属性xmlns:tns="http://abc.de/x/y/z"
为命名空间定义别名/前缀tns
。 DOM api 将为使用 *NS 方法创建的节点隐式添加命名空间。
xmlns
和 xml
是特定命名空间的保留/默认命名空间前缀。 xmlns
(命名空间定义)的命名空间是http://www.w3.org/2000/xmlns/
。
要使用 setAttributeNS() 添加 xmlns:* 属性,请使用 xmlns 命名空间:
mainRootElement.setAttributeNS(
"http://www.w3.org/2000/xmlns/", // namespace
"xmlns:xsi", // node name including prefix
"http://www.w3.org/2001/XMLSchema-instance" // value
);
但即使这样也不需要。就像元素一样,如果您使用它添加属性节点,命名空间定义将被隐式添加。
mainRootElement.setAttributeNS(
"http://www.w3.org/2001/XMLSchema-instance", // namespace
"xsi:schemaLocation", // node name including prefix
"http://abc.de/x/y/z xyzschema.xsd" // value
);
命名空间前缀
如果您看到类似xsi:schemaLocation
的节点名,您可以通过查找xmlns:xsi
属性来解决。此属性是命名空间定义。该值是实际的命名空间。因此,如果您有一个属性xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
,则节点名称可以解析为http://www.w3.org/2001/XMLSchema-instanceschemaLocation
(克拉克符号)。
如果要创建节点,则需要 3 个值:
-
命名空间:
http://www.w3.org/2001/XMLSchema-instance
本地节点名称:schemaLocation
前缀:xsi
前缀对于元素节点是可选的,但对于属性节点是必需的。以下三个xml全部解析为元素节点名http://abc.de/x/y/zcmds
:
<tns:cmds xmlns:tns="http://abc.de/x/y/z"/>
<cmds xmlns="http://abc.de/x/y/z"/>
<other:cmds xmlns:other="http://abc.de/x/y/z"/>
【讨论】:
我用 ...NS 方法尝试过,根节点的创建似乎有效。但是,当我尝试添加属性时出现错误:org.w3c.dom.DOMException: NAMESPACE_ERR: You tried to create or change an object in a way that is incorrect in regards to namespaces
(粗略翻译)。我用新代码更新了主帖
您需要在 createElementNS() 中提供节点的命名空间 - 始终。
但是tns:cmds
节点本身没有命名空间?只有xmlns:xsi
、xsi:schemaLocation
和xmlns:tns
这三个属性可以吗?或者也许我只是没有正确理解命名空间的事情
您当前为命名空间 ``(空)创建元素,前缀为 tns
。您正在尝试为不同的命名空间设置前缀为 xmlns
的属性。 xmlns
是保留前缀。
好的,又改了,更新了原帖。 tns:cmds
和 xsi:schemaLocation
现在可以正常工作,但是,对于其他属性 xmlns:xsi
,仍然会抛出 NAMESPACE_ERR。这个怎么可能?它的构造与第一个起作用的属性完全相同。以上是关于在 Java DOM 中创建以命名空间为前缀的 XML 节点的主要内容,如果未能解决你的问题,请参考以下文章
Java+DOM:如何将没有命名空间的 DOM 树转换为可感知命名空间的 DOM 树?