【问题标题】:Manipulate order of XML element attributes操作 XML 元素属性的顺序
【发布时间】:2013-04-08 09:56:15
【问题描述】:

我读过很多帖子,人们询问有关对 XML 元素强制执行某些属性顺序的问题,一般的回答是它不合法/必需/允许/相关/其他。

我不是在寻找任何回应说我不应该关心属性顺序,所以如果这是你的观点,请不要回复。

我有一个真正的问题需要解决。大型企业产品在其产品的最新版本中将以下两个元素视为不同

<objquestion allowmultiple="true" id="7432" idtext="7433" idvar="7429" parent="7430" questiontype="multchoice">

<objquestion id="7432" idtext="7433" idvar="7429" parent="7430" questiontype="multchoice" allowmultiple="true">

特别是,如果“allowmultiple”属性位于“questiontype”之后,则它充当问题类型的修饰符。如果是之前,则会被忽略 - 不应该。

因此,他们不太可能在短期内修复他们的产品。

我正在使用

操作此 XML 内容
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
doc = dbf.newDocumentBuilder().parse(new InputSource(path));

内部实现会对DOM节点映射中的属性进行排序。当它被写回文件时,它会按照现在的排序顺序写入属性。我有很多使用 XPath 处理 Document 对象的代码。

当我完成对文档的操作后,我现在用

将其写回
Transformer xformer = TransformerFactory.newInstance().newTransformer();
xformer.transform(new DOMSource(lc.getDocument()), new StreamResult(new File(paths[1])));

我需要做的是确保在 questiontype 之后写入 allowmultiple 属性。

我试图了解我是否可以影响用于写回 DOM 树的序列化,或者我是否可以简单地替换一个最初不将属性解析为排序映射的不同实现。我想两者都可以,但我无法找到如何做到这一点。

我查看了 LSSerializer,但我不确定如何拦截该特定元素。我是否必须扩展 FileOutputStream 并寻找一些东西?

我读到 SAX 可能不会进行初始排序,但我需要能够在没有太多新代码的情况下放入解析器,并且对整个 XML 世界并不那么强大。

谁能建议一种方法来做到这一点?

【问题讨论】:

    标签: java xml dom


    【解决方案1】:

    这听起来像是一个 hack,但你可以用 x1allowmultiple 之类的东西重命名这个属性,然后它将是最后一个:

    • 搜索并用 x1allowmultiple 替换所有出现的 allowmultiple
    • 使用 x1allowmultiple 进行处理并创建输出文件
    • 搜索所有出现的 x1allowmultiple 并将其替换为 allowmultiple

    【讨论】:

    • 感谢您的想法。这是我解决问题的最后一种方法,即通过一些 sed 运行最终的 XML 来改变 attrs。
    【解决方案2】:

    下一个 Saxon 版本(9.5,即将到期)有一个序列化属性,允许您控制属性顺序。它是为合法的用例添加的(例如,它可以提高人类的可读性,让 id 属性总是放在第一位),我有点遗憾的是,它最终会被用于像你这样的用例,因为它的无能和不负责任导致大公司雇用的程序员,但就这样吧:如果它解决了问题,我不会哭。

    【讨论】:

    • 谢谢迈克尔,这听起来很有希望。我会看看那个。我对所有不同的框架都有点不知所措,所以你能给我一个指针,说明我需要哪些 Saxon 类来序列化我拥有的 org.w3c.dom.Document。
    • 正如我所说,这是“下一个版本”功能。但是使用 Saxon 的序列化器序列化 DOM 的最简单方法是使用 new net.sf.saxon.TransformerFactoryImpl(). newTransformer() 获取标识转换器,设置所需的序列化参数,然后调用提供 DOMSource 和 StreamResult 的 transform() 方法。
    • 我假设当您谈论设置序列化参数时,您指的是 Transformer 的 OutputProperties,但我想知道如何进行控制。是否有任何关于这将如何工作的讨论或信息?如果在解析过程中属性已经被解析和排序,我不确定我是否理解在转换输出期间如何控制它。
    • Saxon 9.5 现已推出,该功能在这里供参考:saxonica.com/documentation/index.html#!extensions/output-extras/…。这是一个序列化功能,因为它控制结果树转换回词法 XML 的方式。
    【解决方案3】:

    您可以使用this JAXB 方法并查看this 元素属性排序示例。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-26
      • 2011-03-12
      • 1970-01-01
      • 1970-01-01
      • 2012-07-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多