问题描述
首先,一些前提。
我知道网站上存在几个相同的问题,但在这些问题中我都没有找到问题的明确解决方案。 我知道 xml 文件的属性顺序与数据一致性或与实际将 xml 视为此类而不是字符串的软件集成的能力完全无关。但是,我必须保留它,因为我要修改文件,这些文件将由操作员使用 WinMerge 或 Tortoise 的检查修改命令进行目视检查。 我使用过像 DOM、STAX 和 JDOM 这样的库,但结果很差。 在我只需要修改元素文本的文件中,我没有问题,如果有一些不同的格式,我可以轻松地将其视为字符串进行修改。
有了属性就更复杂了。这些按其他顺序排序(请不要质疑这是否正确不是问题所固有的)并且在 winmerge 上看起来是否所有文档都已修改。
这是我的 xml 首先和修改后的(剪切和半随机文本内容)示例
<?xml version="1.0" encoding="UTF-8"?>
<sca:composite xmi:version="2.0"
xmlns:xmi="http://www.omg.org/XMI"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:BW="http://xsd.tns.tibco.com/amf/models/sca/implementationtype/BW" xmlns:XMLSchema="http://www.w3.org/2001/XMLSchema"
xmlns:compositeext="http://schemas.tibco.com/amx/3.0/compositeext"
xmlns:productAvailabilityResp="http://www.example.org/ERTETERET"
xmlns:property="http://ns.tibco.com/bw/property"
xmlns:rest="http://xsd.tns.tibco.com/bERTERTETE"
xmlns:sca="http://www.3453434FDSSDFSD.org/xmlns/sca/1.0"
xmlns:scact="http://xsd.tns.tibco.com/23E23E2E23Ee"
xmlns:scaext="http://2D2333DD32s"
xmi:id="_uKDz4IaiEeipw88nT3HxEA"
targetNamespace="http://tns.tibco.com/D23D32DD2232D2D2"
name="Q1231W1y" compositeext:version="1.0.0"
compositeext:description="TO EDIT VALUE"
ompositeext:formatVersion="2">
</sca:composite>
和
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<sca:composite xmlns:sca="http://www.SDFSDF.org/xmlns/sca/1.0"
xmlns:BW="http://xsd.tns.tibco.com/amf/models/sca/SDFS/BW"
xmlns:XMLSchema="http://www.w3.org/2001/XMLSchema"
xmlns:compositeext="http://schemas.tibco.com/amx/3.0/compositeext"
xmlns:productAvailabilityResp="http://www.example.org/SDFSDFSD"
xmlns:property="http://ns.tibco.com/bw/property"
xmlns:rest="http://xsd.tns.tibco.com/SDFSF"
xmlns:scact="http://xsd.tns.tibco.com/amf/models/sca/SDFSD"
xmlns:scaext="http://xsd.tns.tibco.com/amf/models/sca/extensions"
xmlns:xmi="http://www.omg.org/XMI"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
compositeext:description="test EDITED VALUE"
compositeext:formatVersion="2"
compositeext:version="1.0.0"
name="ERFERFRFE"
targetNamespace="http://tns.tibco.com/bw/composite/ERFERFREy"
xmi:id="_uKDz4IaiEeipw88nT3HxEA"
xmi:version="2.0">
</sca:composite>
我们可以一起尝试寻找解决方案吗?
按照 Federico 的建议进行编辑:
我需要做的是更改单个属性的值和元素的文本内容,我可以做这两件事。但是当我写回文件时,我发现属性的顺序和格式不同:
<?xml version="1.0" encoding="UTF-8"?>
<sca:composite //same attributes
compositeext:description="TO EDIT VALUE"
//same other attributes>
other stuff
</sca:composite>
ps:我的目的是为设计师之外的 tibco BW6 项目制作一个版本控制程序
解决方法
据我所知,您的程序从带有 STaX、DOM 或 SAX 的文件中读取 XML 输入流,然后您对元素或属性进行一些修改,最后您的程序会将数据写入另一个 XML 文件。
要求输出文件的详细结构在进行更改后尽可能接近输入文件的结构。这意味着——除其他条件外——元素和属性在输出文档中的顺序必须与它们在输入文档中的顺序相同。
XML 要求元素的顺序保持原样,但是(正如您已经说过的),属性可以按任何顺序排列,而不会对 XML 文档的语义产生任何影响。
您的问题是,DOM、SAX 和 STaX 都不允许您影响元素的属性顺序。
此描述是否与您的问题相符?
我使用一个大型 XML 文件作为“穷人的数据库”;这意味着我使用文本编辑器操作该 XML 文件,并且我有一堆小程序可以从该 XML 文件创建报告。其中之一将对 XML 文件中的“记录”进行排序,这需要读取它、操作数据并在之后写入。
我和你有同样的(至少是类似的问题):之后有些属性位于任意位置。在编辑器中搜索文本文件时,这会造成很大的摩擦。
因此,我没有使用 SAX、DOM 或 STaX 作为输出,而是编写了自己的库,为每个元素类型定义了一个比较器,用于对该元素类型的属性进行排序。
比较器的一些实现使用了一个包含定义顺序的属性名称的列表,这允许我对属性进行如下排序:
<element sortkey="…" id="…" subject="…" date="…" parent="…" …
如果您将 xmi:…
事物和命名空间定义都视为属性,则此类“XMLWriter”的代码非常简单。
如果每个元素的属性顺序可能不同(即使是相同名称的元素),您必须修改该方法,以便在读取时存储每个元素实例的属性序列。
>但也许 XML 处理根本不适合您……
也许使用 sed
或 awk
之类的方法更适合您的需求。
这基本上意味着您在文本文件中搜索某个序列(使用正则表达式或按行和列号或两者的组合),替换您在那里找到的内容并重新开始在另一个位置进行下一个更改.
编辑:我并不是想将 sed
或 awk
集成到解决方案中;我的意思是只采用这些工具如何工作的基本方法,并在程序中实现它。这两种工具都非常强大,但据我所知,只需要它们的一小部分功能,因此将其中一个完全集成到程序中可能会有些过分——尽管如此,这是可能的: 集成的起点awk
是 awk.sourceforge.net。它甚至可以通过 JSR-223(脚本)进行集成。
对于 sed
的集成,查看 github 上的 tools4j/unix4j project 可能会有所帮助。