【问题标题】:java XMLSerializer avoid Complex Empty Elementsjava XMLSerializer 避免复杂的空元素
【发布时间】:2012-05-23 19:59:57
【问题描述】:

我有这个代码:

    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    DocumentBuilder builder = factory.newDocumentBuilder();
    DOMImplementation impl = builder.getDOMImplementation();
    Document xmldoc = impl.createDocument(null, null, null);

    Element root = xmldoc.createElement("root");
    Element textElement = xmldoc.createElement("text");
    Text textNode = xmldoc.createTextNode("");
    root.appendChild(textElement);
    textElement.appendChild(textNode);

    OutputFormat of = new OutputFormat("XML","UTF-8",true);
    of.setIndent(1);
    of.setIndenting(true);

    ByteArrayOutputStream stream = new ByteArrayOutputStream();

    XMLSerializer serializer = new XMLSerializer(stream, of);
    // As a DOM Serializer
    serializer.asDOMSerializer();
    serializer.serialize(root);

    System.out.println(stream.toString());

我得安慰一下:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <text/>
</root>

但是,我想得到这个:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <text></text>
</root>

有谁知道,如何设置 XMLSerializer 以避免复杂的空元素? 谢谢。

【问题讨论】:

  • 我认为你无法改变这一点。这两个版本是等效的。为什么要避免复杂的空元素?
  • 我的应用程序是两个应用程序之间的一种转换器,它将应用程序1生成的文件解析为一个xml文件,该文件作为应用程序2的输入。但是应用程序2不接受这种的输入。是否有可能通过 doctype 或 st 这样设置?
  • 从语言定义的角度来看,两个版本是等效的,因此在 DTD 或 XSD 中没有构造来防止使用空标签。我的意见是你应该让 app2 接受输入(因为它是一个有效的输入,所以它应该被处理)或者如果你不能访问那个应用程序,你可以改变 app1 返回的 xml 字符串(stream.toString ())。更准确地说,您应该在字符串中查找所有“”模式并将它们替换为“”。我的观点是,为了软件的稳定性,你应该让app2接受空元素的输入
  • 不接受&lt;tag/&gt;的应用不能声称读取XML。

标签: java xmlserializer


【解决方案1】:

结果:我认为这是不可能的。 XMLSerializer 不支持这样的配置。

分析: 当您调用serializer.serialize(root) 时,将调用BaseMarkupSerializer's serialize(Element) 方法。它定义了你传递给序列化的节点类型,并选择适当的方式来处理它。

到了文本节点,调用XMLSerializer's serializeElement(Element)方法:

// If element has children, then serialize them, otherwise
// serialize en empty tag.       
if (elem.hasChildNodes()) {
    //... irrelevant code...
    endElementIO( null, null, tagName );
} else {
    //... irrelevant code...
    _printer.printText( "/>" ); // <------ HARDCODED, NON-CONFIGURABLE
    //... irrelevant code...
}

问题: 如您所见,关闭空元素的方式是硬编码且不可配置的(如果您从源代码中查找完整的代码 sn-p)。

解决方案: 由于 XMLSerializer 不是最终的,您可以通过扩展它并覆盖它的方法来创建自己的序列化器。其中一种方式将发生变化:

_printer.printText( "/>" );

_printer.printText( "</" );
_printer.printText( elem.getTagName() );
_printer.printText( ">" );

意见: 我不确定是否没有干净的解决方案,我认为这个解决方案是最后的解决方案。无论如何,您应该查看源代码和/或文档以获取更多信息。

【讨论】:

  • +1 这在标准 Xerces 序列化程序中绝对不可能。其他序列化程序可能有可能,但我不知道有任何这样做的,也无法在 Google 上找到任何东西。
【解决方案2】:

XMLSerializer 不允许渲染自定义空标签时遇到了同样的问题。我的解决方案是扩展原始 XMLSerializer 代码并覆盖 serializeElement 方法:

我已经复制了原始代码并更改了结束打印部分:

受保护的 void serializeElement(Element elem) 抛出 IOException ...

if (isSelfClosingElement(elem))
    _printer.printText("/>");
else
_printer.printText("></" + elem.getTagName() + ">");

其中 isSelfClosingElement 包含一个自闭合元素列表

注意:另外,您需要复制 printAttribute()printNamespaceAttr() 方法,因为它被标记为私有而不是受保护。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-16
    • 1970-01-01
    相关资源
    最近更新 更多