在Java DOM文档中设置名称空间和前缀
我正在尝试将结果集转换为XML文件。 我首先将这个示例用于序列化在Java DOM文档中设置名称空间和前缀,java,xml,serialization,transformer,Java,Xml,Serialization,Transformer,我正在尝试将结果集转换为XML文件。 我首先将这个示例用于序列化 import org.w3c.dom.bootstrap.DOMImplementationRegistry; import org.w3c.dom.Document; import org.w3c.dom.ls.DOMImplementationLS; import org.w3c.dom.ls.LSSerializer; ... DOMImplementationRegistry registry = DOMImp
import org.w3c.dom.bootstrap.DOMImplementationRegistry;
import org.w3c.dom.Document;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSSerializer;
...
DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();
DOMImplementationLS impl =
(DOMImplementationLS)registry.getDOMImplementation("LS");
...
LSSerializer writer = impl.createLSSerializer();
String str = writer.writeToString(document);
在我完成这项工作之后,我尝试验证我的XML文件,出现了几个警告。
一个是关于没有doctype。所以我尝试了另一种方法来实现这一点。我在变形金刚课上遇到过。这个类允许我设置编码、doctype等
以前的实现支持自动修复命名空间。以下内容不适用
private static Document toDocument(ResultSet rs) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.newDocument();
URL namespaceURL = new URL("http://www.w3.org/2001/XMLSchema-instance");
String namespace = "xmlns:xsi="+namespaceURL.toString();
Element messages = doc.createElementNS(namespace, "messages");
doc.appendChild(messages);
ResultSetMetaData rsmd = rs.getMetaData();
int colCount = rsmd.getColumnCount();
String attributeValue = "true";
String attribute = "xsi:nil";
rs.beforeFirst();
while(rs.next()) {
amountOfRecords = 0;
Element message = doc.createElement("message");
messages.appendChild(message);
for(int i = 1; i <= colCount; i++) {
Object value = rs.getObject(i);
String columnName = rsmd.getColumnName(i);
Element messageNode = doc.createElement(columnName);
if(value != null) {
messageNode.appendChild(doc.createTextNode(value.toString()));
} else {
messageNode.setAttribute(attribute, attributeValue);
}
message.appendChild(messageNode);
}
amountOfRecords++;
}
logger.info("Amount of records archived: " + amountOfRecords);
TransformerFactory tff = TransformerFactory.newInstance();
Transformer tf = tff.newTransformer();
tf.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
tf.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
tf.setOutputProperty(OutputKeys.INDENT, "yes");
BufferedWriter bf = createFile();
StreamResult sr = new StreamResult(bf);
DOMSource source = new DOMSource(doc);
tf.transform(source, sr);
return doc;
}
private static Document to Document(ResultSet rs)引发异常{
DocumentBuilderFactory工厂=DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder=factory.newDocumentBuilder();
Document doc=builder.newDocument();
URL名称空间URL=新URL(“http://www.w3.org/2001/XMLSchema-instance");
String namespace=“xmlns:xsi=“+namespaceURL.toString();
元素消息=doc.createElements(名称空间,“消息”);
文档附件子项(消息);
ResultSetMetaData rsmd=rs.getMetaData();
int colCount=rsmd.getColumnCount();
字符串attributeValue=“true”;
String attribute=“xsi:nil”;
rs.beforeFirst();
while(rs.next()){
数量=0;
元素消息=doc.createElement(“消息”);
messages.appendChild(message);
对于(int i=1;i您没有在根节点中添加名称空间声明;您只是在名称空间中声明了根节点,这是两件完全不同的事情。在构建DOM时,您需要在每个相关节点上引用名称空间。换句话说,当您添加属性时,您需要定义其名称空间(例如,setAttributeNS)
旁注:虽然XML名称空间看起来像URL,但实际上不是。这里不需要使用URL类。在名称空间感知文档上设置节点的正确方法是使用:
rootNode.createElementNS("http://example/namespace", "PREFIX:aNodeName");
因此,您可以用自己的自定义前缀替换“PREFIX”,并用节点名称替换“aNodeName”。为了避免每个节点都有自己的命名空间声明,您可以将命名空间定义为根节点上的属性,如下所示:
rootNode.setAttribute("xmlns:PREFIX", "http://example/namespace");
请确保设置:
documentBuilderFactory.setNamespaceAware(true)
否则您就没有名称空间意识。请注意,使用setAttribute设置xmlns前缀是错误的。
如果要对DOM进行eg签名,必须使用setAttributeNS:
element.setAttributeNS(“http://www.w3.org/2000/xmlns/“,”xmlns:PREFIX“,”http://example/namespace")
谢谢,它现在开始工作了。今天学到了一些新东西,就像每天一样。+1,尽管我不需要调用setNamespaceAware
。该函数的文档表明它与解析相关。请注意,有一个setPrefix(prefix);
允许动态设置前缀的方法。您注意到差异的任何特定示例?当我将DOM转换为文件时,使用setAttribute或SetAttributes会给出相同的输出。您注意到转换修复的运行时DOM中的一些差异吗?这可能会起作用,但您有一个硬编码的命名空间。除非我这是对标准模式的引用,我非常喜欢配置文件中的这些内容。值来自何处并不重要。重要的是,如果使用名称空间,则使用setAttributeNS。@JBert如果它仍然相关(2015):我们在使用XML签名时遇到问题,因为代码使用setAttribute而不是setAttributeNS。签名无法验证。感谢您的答复。因此setAttributesNS
似乎可以正确操作内存中DOM以准备签名,而setAttribute
仅在s之后提供正确的结构序列化(可能是序列化程序修复了问题)。然后,我可以看到内存中DOM上的微小差异会产生不同的XML规范化结果。验证器显然会读取序列化的XML,因此如果签名是从具有“无效”的DOM生成的说明规范化中的差异确实会导致创建无效签名。另请参阅