You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用XMLUnit比较XSD时忽略属性顺序无效的问题求助

问题:XMLUnit忽略XSD属性组内元素顺序差异的解决方案

我有两个XML文件,本质是两个XSD Schema,仅rowattr属性组中的object_level_ind属性顺序不同,希望对比时忽略该差异,但XMLUnit未将它们判定为“相似”。

第一个XSD文件

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

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <xsd:element name="my_export_file">
    <xsd:complexType>
      <xsd:sequence minOccurs="0" maxOccurs="unbounded">
        <xsd:element name="row">
          <xsd:complexType>
            <xsd:attributeGroup ref="rowattr" />
          </xsd:complexType>
        </xsd:element>
      </xsd:sequence>
      <xsd:attributeGroup ref="docelattr" />
    </xsd:complexType>
  </xsd:element>
  <xsd:attributeGroup name="rowattr">
    <xsd:attribute name="subject_level_ind" type="Str.1" use="optional" />
    <xsd:attribute name="object_level_ind" type="Str.1" use="optional" />
    <xsd:attribute name="src_system_id" type="Str.80" use="required" />   
  </xsd:attributeGroup>
  <xsd:attributeGroup name="docelattr">
    <xsd:attribute name="reporting_date" type="xsd:string" />
    <xsd:attribute name="interface_type" type="xsd:string" /> 
  </xsd:attributeGroup>
  <xsd:simpleType name="Str.1">
    <xsd:restriction base="xsd:string">
      <xsd:maxLength value="1" />
    </xsd:restriction>
  </xsd:simpleType>
    <xsd:simpleType name="Str.80">
    <xsd:restriction base="xsd:string">
      <xsd:maxLength value="80" />
    </xsd:restriction>
  </xsd:simpleType>
</xsd:schema>

第二个XSD文件

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

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <xsd:element name="my_export_file">
    <xsd:complexType>
      <xsd:sequence minOccurs="0" maxOccurs="unbounded">
        <xsd:element name="row">
          <xsd:complexType>
            <xsd:attributeGroup ref="rowattr" />
          </xsd:complexType>
        </xsd:element>
      </xsd:sequence>
      <xsd:attributeGroup ref="docelattr" />
    </xsd:complexType>
  </xsd:element>
  <xsd:attributeGroup name="rowattr">
    <xsd:attribute name="subject_level_ind" type="Str.1" use="optional" />
    <xsd:attribute name="src_system_id" type="Str.80" use="required" />
    <xsd:attribute name="object_level_ind" type="Str.1" use="optional" />       
  </xsd:attributeGroup>
  <xsd:attributeGroup name="docelattr">
    <xsd:attribute name="reporting_date" type="xsd:string" />
    <xsd:attribute name="interface_type" type="xsd:string" /> 
  </xsd:attributeGroup>
  <xsd:simpleType name="Str.1">
    <xsd:restriction base="xsd:string">
      <xsd:maxLength value="1" />
    </xsd:restriction>
  </xsd:simpleType>
    <xsd:simpleType name="Str.80">
    <xsd:restriction base="xsd:string">
      <xsd:maxLength value="80" />
    </xsd:restriction>
  </xsd:simpleType>
</xsd:schema>

已尝试的代码

第一种尝试

var fis1 = new FileReader("C:\Users\test1.xsd ");
var fis2 = new FileReader("C:\Users\test2.xsd");
XMLUnit.setIgnoreWhitespace(true);
XMLUnit.setIgnoreAttributeOrder(true);
DetailedDiff diff =  new DetailedDiff(XMLUnit.compareXML(fis1,fis2));
diff.overrideElementQualifier(new ElementNameAndTextQualifier());
List<?> allDifferences = diff.getAllDifferences();
System.out.println(allDifferences);

第二种尝试

DifferenceEvaluator evaluator = DifferenceEvaluators
                .downgradeDifferencesToEqual(ComparisonType.CHILD_NODELIST_SEQUENCE);

Diff diff = DiffBuilder.compare(fis1)
        .withTest(fis2).ignoreComments()
        .ignoreWhitespace()
        .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byName))
        .withDifferenceEvaluator(evaluator)
        .checkForSimilar()
        .build();
System.out.println("Differences: " + diff);

上述尝试后结果均显示:

identical: false
相似  : false

解决思路

  • 核心问题说明:xsd:attribute是XSD中的元素节点,而非XML元素的属性,所以setIgnoreAttributeOrder(true)只对XML元素的属性顺序生效,无法处理XSD里xsd:attribute元素的顺序差异。

  • 自定义节点匹配规则:针对xsd:attributeGroup下的xsd:attribute元素,使用byNameAndAllAttributes规则匹配——只要元素名、name/type/use等属性完全一致,就视为匹配节点,忽略它们在属性组中的顺序。修改后的代码如下:

    Diff diff = DiffBuilder.compare(fis1)
            .withTest(fis2)
            .ignoreWhitespace()
            .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.conditionalBuilder()
                    .whenElementIsNamed("xsd:attribute").thenUse(ElementSelectors.byNameAndAllAttributes())
                    .elseUse(ElementSelectors.byName())
                    .build()))
            .withDifferenceEvaluator(DifferenceEvaluators.downgradeDifferencesToEqual(ComparisonType.CHILD_NODELIST_SEQUENCE))
            .checkForSimilar()
            .build();
    
  • 版本检查:确保使用XMLUnit 2.x版本,1.x版本的API灵活性不足,建议升级到2.x以获得更完善的节点匹配和差异评估能力。

  • 调试验证:可以添加对比监听器打印详细对比过程,确认节点匹配情况,进一步调整规则:

    diff.addListener(new ComparisonListener() {
        @Override
        public void comparisonPerformed(Comparison comparison, ComparisonResult outcome) {
            System.out.println(comparison.getDescription() + " - " + outcome);
        }
    });
    

内容的提问来源于stack exchange,提问作者Abhi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 13:00:46