惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V2EX - 技术
V2EX - 技术
P
Privacy International News Feed
Security Latest
Security Latest
H
Hacker News: Front Page
T
Tenable Blog
The Hacker News
The Hacker News
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
S
Security @ Cisco Blogs
Project Zero
Project Zero
O
OpenAI News
AI
AI
Spread Privacy
Spread Privacy
C
CERT Recently Published Vulnerability Notes
The Last Watchdog
The Last Watchdog
G
GRAHAM CLULEY
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Scott Helme
Scott Helme
Application and Cybersecurity Blog
Application and Cybersecurity Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
C
CXSECURITY Database RSS Feed - CXSecurity.com
NISL@THU
NISL@THU
A
Arctic Wolf
T
Threat Research - Cisco Blogs
PCI Perspectives
PCI Perspectives
N
News and Events Feed by Topic
C
Cyber Attacks, Cyber Crime and Cyber Security
C
Cybersecurity and Infrastructure Security Agency CISA
Simon Willison's Weblog
Simon Willison's Weblog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Know Your Adversary
Know Your Adversary
Google Online Security Blog
Google Online Security Blog
罗磊的独立博客
L
LINUX DO - 最新话题
U
Unit 42
S
Security Affairs
有赞技术团队
有赞技术团队
WordPress大学
WordPress大学
博客园 - 【当耐特】
T
The Exploit Database - CXSecurity.com
S
Schneier on Security
月光博客
月光博客
Engineering at Meta
Engineering at Meta
腾讯CDC
F
Full Disclosure
Cyberwarzone
Cyberwarzone
S
SegmentFault 最新的问题
Recorded Future
Recorded Future
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
博客园 - 司徒正美
The Cloudflare Blog

博客园 - 陈大欠

Step Builder:让对象构建有顺序、有边界、有校验 基于 Attribute 的 AOP 字段校验 浅析 .NET 响应式编程 IObservable与ReactiveX Cron表达式简明教程 正则表达式拾遗 快速批量升级 NugetPackage 版本 C# IEquatable和IEqualityComparer 最佳实践 使用XDT提高开发效率 分析 Dump 入门简明教程 Git commit emoji 对照表 ELK Stack 笔记 HTML5/CSS3(PrefixFree.js) 3D文字特效 Jquery实现图片上下一张 js css 构建滚动边框 使用jquery构建Metro style 返回顶部 使用js实现移动设备访问跳转到指定目录 从一幅图中了解开源世界 Jquery ajax 学习笔记 工欲善其事必先利其器系列之:在VS里面折叠js代码
如何保证XML正确性
陈大欠 · 2023-07-30 · via 博客园 - 陈大欠

如何保证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

参考