比较XML文件以确定哪个是哪个

时间:2016-11-21 22:45:10

标签: c# xml

我们的软件吐出了许多xml文件,我需要确定哪个是哪个。例如,有三种不同类型的xml文件(严重缩写):

“IQ.xml”

<?xml version="1.0" encoding="ISO-8859-1"?>
<Catalog xmlns:dt="urn:schemas-microsoft-com:datatypes">
<Rec>
<ITEM dt:dt="string"></ITEM>
<QTY dt:dt="string"></QTY>
</Rec>
</Catalog>

“IMR.xml”

<?xml version="1.0" encoding="ISO-8859-1"?>
<Catalog xmlns:dt="urn:schemas-microsoft-com:datatypes">
<Rec>
<ITEMS dt:dt="string"></ITEMS>
<MFG dt:dt="string"></MFG>
<ROUTE dt:dt="string"></ROUTE>
</Rec>
</Catalog>

“RP.xml”

<?xml version="1.0" encoding="ISO-8859-1"?>
<Catalog xmlns:dt="urn:schemas-microsoft-com:datatypes">
<Rec>
<REF dt:dt="string"></REF>
<PON dt:dt="string"></PON>
</Rec>
</Catalog>

任何这些都可以随时传递出来,我需要一种方法来确定将这些文件传递到的位置。实现这一目标的最佳方法是什么?是否可以使用模式根据字段测试xml文件,然后传回结果?

我最初的想法是测试一个架构,如果它与第一个不匹配,继续到第二个,依此类推。然后对其进行硬编码,并且在以后添加不同的XML文件类型时无法更改,因此我对此不太热衷。我现阶段不确定这是否是最好的方法?

这将用C#编码,所以我不确定是否有任何可以帮助的内置函数或是否必须自定义编写。

以前有人需要这样做吗?你是怎么解决的?

2 个答案:

答案 0 :(得分:0)

我建议的是通过模式验证XML文件(就像你自己建议的那样)。

关于您的代码灵活性以及以后支持其他架构的问题,有很多选择,但这取决于您想要做什么。

例如,您可以将所有架构保存为配置文件,当您验证新的XML文件时,如果没有匹配,您可以通过支持的架构以编程方式运行它。您可以抛出例外(例如,不支持的XML文件结构)。

您还可以定义某些XML文件与某些架构之间的静态组合,稍后您可以通过编程方式进行推理。

当然,当您想要支持新架构时,您需要更改代码......但这是正常行为。

要创建处理任何类型的XML文件和任何类型的架构的完全通用且自动化的方法将是困难的,并且您需要使用某种命名约定,其中您将从中推导出关联的架构。名称或XML文件中嵌入的一些信息。这可以在运行时完成,但即使这样,您可能只支持有限数量的行为,并且当您想要扩展应用程序时,您将需要新的代码。

答案 1 :(得分:0)

使用XmlReader XmlReaderSettings指定要执行的验证类型和ValidationEventHandler。这可以包装到一个方法中,该方法将为您提供成功验证XML文档的模式或模式。

如果您担心将来添加新模式,那么只需将它们存储在类似目录的中心位置,然后在运行时抓取它们。可以根据需要将新模式简单地放入目录中。

void Main()
{
    var rootDirectory = @"C:\Testing";
    var schemaDirectory = Path.Combine(rootDirectory, "Schemas");
    var dataDirectory = Path.Combine(rootDirectory, "Data");

    var schemaFiles = new[] {
        Path.Combine(schemaDirectory, "IQ.xsd"),
        Path.Combine(schemaDirectory, "IMR.xsd"),
        Path.Combine(schemaDirectory, "RP.xsd")
    };

    var dataFiles = new[] {
        Path.Combine(dataDirectory, "IQ.xml"),
        Path.Combine(dataDirectory, "IMR.xml"),
        Path.Combine(dataDirectory, "RP.xml")
    };

    var results = FindMatchingSchemas(dataFiles[1], schemaFiles).Dump();
    Console.WriteLine("Matching schema is: {0}", results.First(r => r.Value));
}

private static Dictionary<string, bool> FindMatchingSchemas(string dataFile, string[] schemaFiles)
{
    var results = new Dictionary<string, bool>();

    foreach (var schemaFile in schemaFiles)
    {
        results.Add(schemaFile, true);

        // Set the validation settings.
        XmlReaderSettings settings = new XmlReaderSettings();
        settings.ValidationType = ValidationType.Schema;
        settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema;
        settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
        settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
        settings.ValidationEventHandler += new ValidationEventHandler((object sender, ValidationEventArgs args) =>
        {
            // Validation error
            results[schemaFile] = false;
        });
        settings.Schemas.Add(null, schemaFile);

        // Create the XmlReader object.
        XmlReader reader = XmlReader.Create(dataFile, settings);

        // Parse the file.
        while (reader.Read());
    }

    return results;
}

// Output: Matching schema is: C:\Testing\Schemas\IMR.xsd

有一个免费网站可以从XML文档生成XSD文档。 http://www.freeformatter.com/xsd-generator.html

IQ.xsd

<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="Catalog">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="Rec">
          <xs:complexType>
            <xs:sequence>
              <xs:element type="xs:string" name="ITEM"/>
              <xs:element type="xs:short" name="QTY"/>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

IMR.xsd

<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="Catalog">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="Rec">
          <xs:complexType>
            <xs:sequence>
              <xs:element type="xs:short" name="ITEMS"/>
              <xs:element type="xs:string" name="MFG"/>
              <xs:element type="xs:string" name="ROUTE"/>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

RP.xsd

<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="Catalog">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="Rec">
          <xs:complexType>
            <xs:sequence>
              <xs:element type="xs:string" name="REF"/>
              <xs:element type="xs:short" name="PON"/>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

派生自Validating an XML against referenced XSD in C#