【问题标题】:Avoid to generate XML self-closing tags for empty elements AND generate a custom <xml> start tag避免为空元素生成 XML 自闭合标签并生成自定义 <xml> 开始标签
【发布时间】:2020-09-24 14:59:58
【问题描述】:

我需要生成一个包含一些数据的 XML 文件,以发送到我没有实际操作的第 3 方系统(由另一家公司制造,我无法修改或要求修改)

这个其他系统不接受我生成的文档,因为它有一些用于空元素的自闭合标签:&lt;tag/&gt; 而不是 &lt;tag&gt;&lt;/tag&gt;

我当前的代码是这样的

TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.ENCODING, "ISO-8859-1");
StreamResult streamResult = new StreamResult(file);
transformer.transform(source, streamResult);

为了生成全结束标签,我尝试让Transformer 使用html 输出方法:

transformer.setOutputProperty(OutputKeys.METHOD, "html");

来源:http://makble.com/the-self-closing-tag-problem-of-javaxxmltransform-package-dom-to-source

这可以使用完整的结束标签,但我还有其他问题:

  • 没有生成XML文档起始标签(如&lt;?xml version="1.0" encoding="ISO-8859-1" standalone="no"?&gt;
  • 特殊字符以 HTML 方式生成(例如 &amp;eacute; 而不是 é

所以我发现我可以像这样使用StAXResult 而不是StreamResult

        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        XMLStreamWriter writer = XMLOutputFactory.newFactory().createXMLStreamWriter(new BufferedWriter(new FileWriter(nomFichier)));
        StAXResult streamResult = new StAXResult(writer);
        transformer.transform(source, streamResult);

这也适用于在空元素上使用完整的结束标记,但我的 XML 文档开始标记不完整:

<?xml version="1.0"?>

如果我尝试使用 Transformer 的输出属性来定义它,这不起作用:

        Transformer transformer = transformerFactory.newTransformer();
        transformer.setOutputProperty(OutputKeys.METHOD, "xml");
        transformer.setOutputProperty(OutputKeys.VERSION, "1.0");
        transformer.setOutputProperty(OutputKeys.ENCODING, "ISO-8859-1");
        transformer.setOutputProperty(OutputKeys.STANDALONE, "no");

由于使用了StAXResult,所有属性都被忽略

Michael Kay (https://stackoverflow.com/users/415448/michael-kay) 在Processing xml file (Java) 中明确表示:

调用Transformer.setOutputProperty(OutputKeys.ENCODING, "ISO-8859-1"); 无效,除非变压器正在生产 序列化输出。在您的情况下,变压器不生产 序列化输出,因为您将输出发送到 StAXResult

我尝试配置 XMLStreamWriter 至少来定义编码:

        XMLStreamWriter writer = XMLOutputFactory.newFactory().createXMLStreamWriter(new BufferedWriter(new FileWriter(nomFichier)));
        writer.writeStartDocument("ISO-8859-1", "1.0");
        StAXResult streamResult = new StAXResult(writer);
        transformer.transform(source, streamResult);

这会导致添加“正确”的起始 XML 标记,但我也有来自 Transformer 的默认标记:

<?xml version="1.0" encoding="ISO-8859-1"?><?xml version="1.0"?>

最后我尝试删除 Transformer 默认标签:

        Transformer transformer = transformerFactory.newTransformer();
        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");

但正如已经说过的那样,这不起作用,因为 Transformer 的输出属性被忽略了......

我有什么想法可以同时拥有所有这些吗?

  • 有效的 XML 起始标签 (&lt;?xml version="1.0" encoding="ISO-8859-1" standalone="no"?&gt;)
  • 正确的字符编码(é 而不是&amp;eacute;
  • 元素为空时的完整结束标记(&lt;tag&gt;&lt;/tag&gt; 而不是&lt;tag/&gt;

我看到的唯一方法是使用XMLStreamWriterStAXResult 编写文档,然后处理生成的文件以解析它并删除&lt;?xml version="1.0"?&gt; 元素并将其替换为硬编码的&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt; 字符串,但我并不想仅仅为此解析我生成的 XML 文件,因为它可能非常大。

我正在寻找更优雅的解决方案!

提前感谢您的帮助。

【问题讨论】:

    标签: java xml xslt


    【解决方案1】:

    如果你想避免 XML 自闭合标签,你可以使用

    @JsonProperty(value = "TEST")
    @JsonSerializer(nullsUsing = NullSerializer.class)
    private String test;
    

    NullSerializer:是从JsonSerializer扩展而来的类,返回null。

    因此,如果“test”变量为空,生成的 XML 消息将如下所示:

    <TEST></TEST>
    

    代替:

    <TEST/>
    

    【讨论】:

    • 问题是我不能使用带有注释的变量,因为我从来自数据库的结构化对象动态生成 XML 内容:Element tag = document.createElement("mytag"); tag.appendChild(document.createTextNode(object.getXXX() != null ? object.getXXX().toString() : "")); 如果我必须设置我生成的每个值进入一个类变量,这将是超级重... :-/
    【解决方案2】:

    如果要创建文件,为什么要使用 StAXResult?正如您在回答中提到的那样,您正在将一个树结构转换为另一个树结构。 XML 从不序列化,因此不考虑序列化设置。

    您的主要问题似乎是您希望避免使用自关闭标签,但这没有任何意义,因为自关闭标签在语义上与一对打开/关闭标签相同。我认为唯一的解决方法是使用 XSLT,您可以在其中通过添加一些不会在两者之间产生任何输出的内容来欺骗处理器编写一个开始和结束标记。但这大概也取决于您的处理器。最后,您试图将 XML 发送到无法理解 XML 的系统,因此您将始终不得不求助于黑客。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-12-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多