如何“规范化”任意xml(通过重新排序所有属性和元素)

时间:2014-08-21 12:07:17

标签: java xml xslt jaxb

我有一些代码从一组带有jaxb注释的类生成* .xsd文件:

JAXBContext context = //build from set of classes
final DOMResult result = new DOMResult(); //will hold xsd output
context.generateSchema(new SchemaOutputResolver() {
    @Override
    public Result createOutput(String namespaceUri, String suggestedFileName) throws IOException {
       return result;
    }
});
Document doc = result.getNode();
OutputFormat format = new OutputFormat(doc);
format.setIndenting(true);
StringWriter writer = new StringWriter();
XMLSerializer serializer = new XMLSerializer(writer, format);
serializer.serialize(doc);
String xsd = writer.toString();

问题是xsd生成(存储在xsd中)是随机顺序 - 使用相同输入的2次运行可能会生成逻辑上相同的xsds但是元素顺序不同,这会对diff工具造成严重破坏写出来。

如何i"规范化" xsd内的xml?

我在相关问题中看到了对xslt的其他一些引用,但我看到的任何内容都需要提前列出元素。我正在寻找适用于任何xml输入的东西。

1 个答案:

答案 0 :(得分:2)

没有公共规范我知道尝试为XSD架构文档指定规范形式。所以不会有现成的工具;你必须自己动手或决定(正如MathiasMüller所说)差异不是你的朋友。

请注意,现成的规范化工具可以规范化输入文档中属性值规范的顺序,但它们永远不会尝试规范化元素序列,因为在一般情况下,元素序列在XML中很重要

当我遇到这种情况时,我已经指定了一个“规范”形式,可以最大限度地减少头痛(以alpha顺序列出所有顶级元素,然后按alpha顺序列出所有顶级复杂类型,然后所有顶级简单类型的alpha顺序,...)并编写一个XSLT样式表来适当地对元素进行排序。

如果这足以满足您的目的(也就是说,如果它是导致您出现问题的顶层构造的序列),那么这很容易做到(假设您有足够的XSLT知识来编写一个近似身份变换,可以进行排序顶级声明,或者可以在其他技术中编写等效转换。)

如果模式生成在各个声明的结构上也不一致,那么您可能还需要规范化声明结构(按字母顺序对xsd:choice的子项进行排序,按字母顺序或按类型排序属性引用和声明你喜欢,规范模型组结构,...)。根据您的模式生成器如何改变它的输出,这在理论上可以变得任意复杂。但在实践中,我希望这个问题对于任何对XSD和XSLT(或其他一些XML处理技术)有足够了解的人来说都是易于理解的。

当然,您还必须采取措施来控制模式文档中的换行符和空格;缩进输出的XSLT序列化控件应该可以帮到你。