如何防止JDOM2中的XMLOutputter切割属性名称(名称空间部分)?

罗兰

我试图从JDOM 1.0更新到JDOM2。在JDOM 1.0中,此代码:

DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
org.w3c.dom.Document doc = dbFactory.newDocumentBuilder().newDocument();
doc.setXmlVersion("1.0");

Element root = doc.createElement("Document");

root.setAttribute("xmlns", "urn:iso:foo");
root.setAttribute("xsi:schemaLocation", "urn:iso:foo bar.xsd");
root.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
doc.appendChild(root);

Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("testxml.xml"), "UTF8"));
DOMBuilder builder = new DOMBuilder();
Document jdoc = builder.build(doc);
XMLOutputter fmt = new XMLOutputter();
fmt.setFormat(Format.getPrettyFormat());
fmt.output(jdoc, out);

生成此XML文件:

<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:iso:foo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:iso:foo bar.xsd" />

当我使用JDOM2时,属性xsi:schemaLocation更改为schemaLocation(XML看起来像这样):

<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:iso:foo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" schemaLocation="urn:iso:foo bar.xsd" />

有没有办法将xsi:零件保留在JDOM2中?没有它,处理生成的XML的系统将无法读取它(不在我的控制之下)。不确定是否是相同的问题。

罗尔夫

JDOM要求使用支持名称空间的DOM实现来构建JDOM文档。

我整理了以下代码来说明这一点:

import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.StringReader;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.jdom2.Document;
import org.jdom2.input.DOMBuilder;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;
import org.w3c.dom.Element;
import org.xml.sax.InputSource;


public class DOMvsJDOM {

    private static org.w3c.dom.Document buildDOM(String xml) throws Exception {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(true);
        dbf.setValidating(false);
        dbf.setExpandEntityReferences(false);
        DocumentBuilder db = dbf.newDocumentBuilder();
        StringReader sr = new StringReader(xml);
        InputSource is = new InputSource(sr);
        return db.parse(is);
    }

    public static void printDocument(org.w3c.dom.Document doc, OutputStream out) throws Exception {
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer transformer = tf.newTransformer();
        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
        transformer.setOutputProperty(OutputKeys.METHOD, "xml");
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
        transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");

        transformer.transform(new DOMSource(doc), 
             new StreamResult(new OutputStreamWriter(out, "UTF-8")));
    }

    private static void parseUsingJDOM(org.w3c.dom.Document doc) throws Exception {
//      Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("testxml.xml"), "UTF8"));
      DOMBuilder builder = new DOMBuilder();
      Document jdoc = builder.build(doc);
      XMLOutputter fmt = new XMLOutputter();
      fmt.setFormat(Format.getPrettyFormat());
      fmt.output(jdoc, System.out);
    }

    public static void main(String[] args) throws Exception {
        DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
        org.w3c.dom.Document doc = dbFactory.newDocumentBuilder().newDocument();
        doc.setXmlVersion("1.0");

        Element root = doc.createElement("Document");

        root.setAttribute("xmlns", "urn:iso:foo");
        root.setAttribute("xsi:schemaLocation", "urn:iso:foo bar.xsd");
        root.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
        doc.appendChild(root);

        printDocument(doc, System.out);

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        printDocument(doc, baos);

        System.out.println("JDOM Using captured");
        parseUsingJDOM(doc);

        String xml = new String(baos.toByteArray());
        doc = buildDOM(xml);

        System.out.println("JDOM Using parsed");
        parseUsingJDOM(doc);

    }
}

请注意,该代码的作用是手动构建DOM,将其输出,从DOM构建JDOM,将其输出,然后将DOM作为字符串输出,将String重新解析为DOM,然后从重新构建JDOM。解析的XML。

这是输出(我在输出中手动添加了换行符,以使实际的DOM字符串在其自己的行上具有XML声明):

<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:iso:foo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:iso:foo bar.xsd"/>
JDOM Using captured
<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:iso:foo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" schemaLocation="urn:iso:foo bar.xsd" />
JDOM Using parsed
<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:iso:foo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:iso:foo bar.xsd" />

最重要的是,产生输出的DOM从技术上讲不是“名称空间感知”的,因此不能满足JDOM 2.0的期望。

现在,您使用以下代码来设置属性:

root.setAttribute("xmlns", "urn:iso:foo");
root.setAttribute("xsi:schemaLocation", "urn:iso:foo bar.xsd");
root.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");

如果改用支持名称空间的版本:

    root.setAttribute("xmlns", "urn:iso:foo");
    root.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
    root.setAttributeNS("http://www.w3.org/2001/XMLSchema-instance", "xsi:schemaLocation", "urn:iso:foo bar.xsd");
    doc.appendChild(root);

然后JDOM会正确处理。

这就是JDOM在上面的“从字符串解析”版本中工作的原因,因为解析是通过名称空间感知的方式完成的。

因此,JDOM要求在处理DOM内容时,DOM内容应采用可识别XML命名空间的格式。这就是为什么我的测试都可以工作的原因,因为我的DOM内容都可以识别名称空间。

不幸的是,这不能解决您遇到的实际问题。

在这种情况下,JDOM2应该与JDOM 1.x兼容,并且不兼容是一个问题。JDOM2正在做“正确”的事情,但它也可能也应该做“错误”的事情,并坚持为未正确声明的DOM上定义的那些属性寻找名称空间。

我创建了第138期来对此进行跟踪:https : //github.com/hunterhacker/jdom/issues/138

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

JDOM2 xpath在不同名称空间中查找节点

来自分类Dev

带有XPath的JDOM2不适用于名称空间

来自分类Dev

Java:如何从Java中的xml获取属性名称?(JDOM)

来自分类Dev

在箱形图的x轴上切割的名称

来自分类Dev

如何添加处理指令[jdom2]

来自分类Dev

如何防止 osmconvert 在纬度/经度中切割最后 2 位数字

来自分类Dev

如何防止SOAP wsdl中的名称空间包装器标签?

来自分类Dev

如何在JDOM2中使用XPATH函数(concat,string-join)?

来自分类Dev

如何防止访问Admin名称空间

来自分类Dev

我们可以在JDOM中更改XML名称空间变量名称吗?

来自分类Dev

如何从Powershell输出中删除属性名称空间?

来自分类Dev

如何在UIImage中“切割”透明孔?

来自分类Dev

如何在directx 9中切割对象

来自分类Dev

如何删除属性的名称空间前缀?

来自分类Dev

xmlns属性中名称空间的值

来自分类Dev

xml中名称空间在属性上的范围

来自分类Dev

xml名称空间的属性

来自分类Dev

如何在情节中切割子图底部的大空间?

来自分类Dev

如何防止输入在不改变高度的情况下切割字母的尾部?

来自分类Dev

尚未声明带有前缀“ uml”的JDOM2命名空间

来自分类Dev

如何切割和更换琴弦

来自分类Dev

如何取消缓冲切割?

来自分类Dev

如何切割和更换琴弦

来自分类Dev

裁剪时如何切割

来自分类Dev

执行透视变形时,如何避免图像的一部分被切割?

来自分类Dev

在查询中获取切割的 JSON

来自分类Dev

使用 bash 中的 cut 切割字符串的特定部分

来自分类Dev

如何防止XmlDocument.Save编写新元素的名称空间?

来自分类Dev

如何防止在Firefox中生成空名称空间?

Related 相关文章

热门标签

归档