如何保证XML正确性

如何保证XML正确性

XML是个盒子,什么都能装,但是装进去的东西正确与否恐怕无法得知。往往我们都人工审核、双人复核保证,但是次数多了难免会出错。那么我们如何保证和避免这种问题出现呢?
那就是XSD,当然还有XMLSpy等付费解决方案不在考虑范围内。

JSON也是有Schema的有兴趣可以自行了解下~

DTD & XSD

DTD(Document Type Definition)是一种用于定义XML文档结构的技术。它是一种基于文本的声明,用于定义XML文档的元素、元素的层次结构、属性和实体等规则,从而约束XML文档的合法性

DTD主要用于描述XML文档的结构和约束条件,包括:

  1. 元素声明:定义了XML文档中可能包含的元素,以及元素之间的层次结构和顺序。元素声明指定了元素名称和其内容模型(如子元素的数量和顺序)。

  2. 属性声明DTD允许定义元素可能包含的属性及其数据类型。属性声明指定了属性名称和其数据类型,以及可能的默认值。

  3. 实体声明DTD允许定义实体(entity),用于定义文本片段的缩写或替换。实体可以包含特殊字符、实体引用或外部实体的引用。

  4. CDATA定义:通过CDATA定义,DTD可以指定一段文本内容不进行解析,而直接原样输出。

DTD本身也是一个XML文档,但其语法比XML简单,通常使用文本格式进行定义。DTD定义文件通常以DTD.ent为扩展名。

DTD是一种被广泛使用的XML文档约束技术,在早期XML发展阶段使用非常广泛。它对于简单的XML文档结构定义和验证非常有效,但也存在一些局限性。

XSD(XML Schema Definition)是一种用于定义XML文档结构和内容约束的技术。它是一种基于XML的语言,用于描述XML文档的合法结构和数据类型。XSD定义了XML文档应该包含哪些元素、元素的层次结构、数据类型、默认值等规则,从而允许验证和验证XML文档的有效性

XSD可以用于以下几个方面:

文档结构定义:XSD定义了XML文档的元素、元素的层次结构和顺序,以及元素之间的关系。通过XSD,可以确保XML文档按照指定的结构进行组织和嵌套。

数据类型定义:XSD定义了XML文档中元素和属性的数据类型,例如字符串、整数、日期等。这样可以确保文档中的数据类型符合规定,避免了无效或不一致的数据。

数据约束和验证:XSD可以定义元素和属性的取值范围、长度、枚举值等约束条件。通过这些约束,可以验证XML文档是否符合规定,从而确保数据的有效性和一致性。

文档注释和文档说明:XSD支持添加注释和文档说明,使得XML文档结构和含义更易于理解和维护。

XSD本身也是一个XML文档,使用特定的元素和属性来定义XML文档结构和约束条件。常见的XSD定义元素包括xs:schemaxs:elementxs:complexTypexs:simpleType等。

XSD和DTD的优劣取舍

XSD的使用对于数据交换、数据存储和Web服务等场景非常重要。通过使用XSD,可以定义明确的XML文档结构,帮助开发人员和系统正确解析、生成和验证XML数据。同时,XSD还可以作为文档规范的一部分,促进不同系统之间的数据交换和集成。

DTD(Document Type Definition)和XSD(XML Schema Definition)都是用于定义XML文档结构和约束条件的技术,但它们之间存在一些重要的区别:

  1. 语法:

    • DTD使用一种简单的文本格式来定义XML文档结构和约束条件,其语法相对简单直观,但不够灵活。
    • XSD则是一个基于XML的语言,本身也是一个XML文档,它使用XML的元素和属性来定义XML文档的结构和约束条件,因此语法更加复杂,但也更加灵活和强大。
  2. 功能:

    • DTD的功能相对有限,主要用于描述XML文档的基本结构、元素、属性和实体,它不支持命名空间和数据类型的精确定义。
    • XSD功能更加丰富,它支持命名空间,可以更精确地定义数据类型和数据约束,支持复杂类型的定义,以及更复杂的模式验证和数据处理。
  3. 灵活性:

    • DTD的约束较为简单,不支持复杂数据类型和结构定义,因此其灵活性相对较低。
    • XSD支持更多的数据类型定义、结构定义和约束条件,使得它具有更高的灵活性和扩展性。
  4. 兼容性:

    • DTDXML早期定义技术,由于其简单性和广泛应用,它仍然被许多遗留系统和早期XML文档所使用,具有一定的兼容性优势。
    • XSDXML Schema的标准规范,它在功能上更为强大和灵活,但可能不被一些早期的XML处理程序所支持。

总体而言,如果需要简单的XML文档结构定义和验证,或者对于兼容性要求较高的情况,可以选择使用DTD。而如果需要更复杂和精确的XML文档约束,以及更好的灵活性和扩展性,XSD则是更好的选择。随着XML技术的发展,XSD逐渐成为主流的XML文档约束技术,并取代了DTD在许多场景的应用。

使用 XSD.exe 对 XML 文件生成 XSD 架构文件

XML 架构定义工具 (XSD.exe) 通常可在以下路径中找到:C:\Program Files (x86)\Microsoft SDKs\Windows\{version}\bin\NETFX {version} Tools\

GrayControlConfig配置文件举例

<GrayControlConfig XMLns:xsi="http://www.w3.org/2001/XMLSchema-instance" XMLns:XSD="http://www.w3.org/2001/XMLSchema">
    <GrayControls>
        <GrayControlConfigItem Name="ProfileConsumerByOpenApp" EnableGrayControl="1" EnableAllowTenantIds="true" EnableAllowAllTenant="false">
            <AllowTenantIds>
                <AllowTenantId>100001</AllowTenantId>
            </AllowTenantIds>
        </GrayControlConfigItem>
        <GrayControlConfigItem Name="StaffAndOrgSubPath" EnableGrayControl="false" EnableAllowTenantIds="true" EnableBlockTenantIds="false" EnableAllowTenantIdStartNum="false" EnableAllowAllTenant="false" EnableGrayMultiWrite="true">
            <AllowTenantIds>
                <AllowTenantId>-1</AllowTenantId>
            </AllowTenantIds>
        </GrayControlConfigItem>
    </GrayControls>
</GrayControlConfig>

下面的命令从GrayControlConfig.xml生成一个XSD架构文件

**********************************************************************
** Visual Studio 2017 Developer Command Prompt v15.9.50
** Copyright (c) 2017 Microsoft Corporation
**********************************************************************

C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools>xsd.exe D:\GrayControlConfig.xml /outputdir:D:\
Microsoft(R) Xml 架构/数据类型支持实用工具
[Microsoft (R) .NET Framework, Version 4.8.3928.0]
Copyright (C) Microsoft Corporation. All rights reserved.
正在写入文件“D:\GrayControlConfig.xsd”。

C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools>

可以看到生成的XSD文件如下,但是AllowTenantId我们预期是数字类型,我们可以手动改一下。

图 6

<?XML version="1.0" encoding="utf-8"?>
<xs:schema id="GrayControlConfig" XMLns="" XMLns:xs="http://www.w3.org/2001/XMLSchema" XMLns:msdata="urn:schemas-microsoft-com:XML-msdata">
  <xs:element name="GrayControlConfig" msdata:IsDataSet="true" msdata:Locale="en-US">
    <xs:complexType>
      <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:element name="GrayControls">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="GrayControlConfigItem" minOccurs="0" maxOccurs="unbounded">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element name="AllowTenantIds" minOccurs="0" maxOccurs="unbounded">
                      <xs:complexType>
                        <xs:sequence>
                          <xs:element name="AllowTenantId" type="xs:string 改成 XSD:unsignedInt" minOccurs="0" />
                        </xs:sequence>
                      </xs:complexType>
                    </xs:element>
                  </xs:sequence>
                  <xs:attribute name="Name" type="xs:string" />
                  <xs:attribute name="EnableGrayControl" type="xs:string" />
                  <xs:attribute name="EnableAllowTenantIds" type="xs:string" />
                  <xs:attribute name="EnableAllowAllTenant" type="xs:string" />
                  <xs:attribute name="EnableBlockTenantIds" type="xs:string" />
                  <xs:attribute name="EnableAllowTenantIdStartNum" type="xs:string" />
                  <xs:attribute name="EnableGrayMultiWrite" type="xs:string" />
                </xs:complexType>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:choice>
    </xs:complexType>
  </xs:element>
</xs:schema>

Visual Studio 外部工具调用 XSD.exe

使用VS的外部工具,工具 -> 外部工具 -> 添加

  • 标题:XSD(任意即可)
  • 命令:C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools
  • 参数:$(ItemFileName)$(ItemExt)
  • 初始目录:$(ItemDir)
  • 使用输出窗口:(可选,方便调试)
  • 提示输入参数:(可选,方便调试可以看到具体参数)

图 2

在解决方案中选中一个XML文件,然后选择工具->XSD,就会生成一个XSD文件,他会生成在选中文件同目录中。此时选择显示所有文件然后包含在内即可。

输出窗口的日志

Microsoft(R) xml 架构/数据类型支持实用工具
[Microsoft (R) .NET Framework, Version 2.0.50727.3038]
Copyright (C) Microsoft Corporation. All rights reserved.
正在写入文件“D:\Source\XXX\Configuration\Configuration\Configuration\Account_Common\GrayControlConfig.xsd”。

如何验证XML?

Visual Studio XML工具

在解决方案中打开一个XML文件,然后选择XML->创建架构,就会生成一个XSD文件,他会生成XSD文件,文件会在C:\Users\XXX\AppData\Local\Temp\XX.xsd中。可以手工将其复制到项目中。
选择XML菜单点击架构选项,点击添加选择我们刚才生成的xsd文件,
文件VS会自动去验证XSD文件,如果XSD文件有错误,会在XML文件中显示错误信息。

图 3

自定义 GUID 类型验证

AppId是一个GUID的字符串,但是我们如何保证他是标准的00000000-0000-0000-0000-000000000000标准格式呢?

<SystemManageMapping majorVersion="1" minorVersion="141">
  <Applications>
    <Application AppId="2EC95F56-8331-4CA9-9423-1FABCE30D653" AppName="APP1" AppType="6" ProductId="CCBAAACA-B8F7-404E-B626-C02006EEEF40" ProductName="APP1" Chinese="应用1"/>
    <Application AppId="15E6E58A-5965-459E-BF55" AppName="APP2" AppType="4" ProductId="" ProductName="APP2" Chinese="应用2"/>
  </Applications>
</SystemManageMapping>

自定义XSD simpleType类型,使用正则去验证它,当然还有其余各种类型,我们只是用GUID举个例子

<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/xmlSchema">
	<xs:element name="SystemManageMapping">
		<xs:complexType>
			<xs:sequence>
				<xs:element name="Applications">
					<xs:complexType>
						<xs:sequence>
							<xs:element maxOccurs="unbounded" name="Application">
								<xs:complexType>
									<xs:attribute name="AppId" type="GUID" use="required" />
								</xs:complexType>
							</xs:element>
						</xs:sequence>
					</xs:complexType>
				</xs:element>
			</xs:sequence>
		</xs:complexType>
	</xs:element>
	<xs:simpleType name="GUID">
		<xs:restriction base="xs:string">
			<xs:pattern value="([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})|(\{[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\})"/>
		</xs:restriction>
	</xs:simpleType>
</xs:schema>

可以看到验证器成功的验证了数据类型。

图 4

使用代码验证

使用 Linq to XML XmlSchemaSet 去验证


internal class Program
{
    private static void Main(string[] args)
    {
        XmlSchemaSet schemas = new XmlSchemaSet();
        schemas.Add("", $"{Environment.CurrentDirectory}/Account_Common/GrayControlConfig.xsd");
        Console.WriteLine("Attempting to validate");
        XDocument custOrdDoc = XDocument.Load($"{Environment.CurrentDirectory}/Account_Common/GrayControlConfig.xml");

        bool isError = false;
        custOrdDoc.Validate(schemas, (o, e) =>
        {
            isError = true;
            ErrorLog(e.Message);
        });

        if (isError)
            DebugLog("Error end");
        else
            DebugLog("Success end", ConsoleColor.Green);

        Console.ReadKey();
    }

    internal static void DebugLog(string msg, ConsoleColor color = ConsoleColor.Yellow)
    {
        ConsoleColor currentColor = Console.ForegroundColor;
        Console.ForegroundColor = color;
        Console.WriteLine(msg);
        Console.ForegroundColor = currentColor;
    }

    internal static void ErrorLog(string msg)
    {
        ConsoleColor currentColor = Console.ForegroundColor;
        Console.ForegroundColor = ConsoleColor.Red;
        Console.WriteLine(msg);
        Console.ForegroundColor = currentColor;
    }
}

可以看到输出日志中AllowTenantId字段无法通过验证

图 7

Attempting to validate
“AllowTenantId”元素无效 - 根据数据类型“http://www.w3.org/2001/XMLSchema:int”,值“-1fff”无效 - 字符串“-1fff”不是有效的 Int32 值。
Error end

参考

posted @ 2023-07-30 01:00  陈大欠  阅读(73)  评论(1编辑  收藏  举报