如何使不符合模式的XML无效?

时间:2017-10-09 15:18:22

标签: xml xsd xsd-validation

我知道StackOverflow中已多次询问此问题并尝试了解决这些问题的所有解决方案。但是,在我的情况下,我创建的模式仅在我尝试使用包含Schema中存在的元素的XML进行验证时才有效。例如,我有一个XML包含<Users></Users>元素,它存在于我的Schema中。

我想要的是使所有不符合我的Schema的XML无效。因此,如果XML确实具有<Users></Users>,则验证应该抛出豁免。

以下是模式,我按文件和命名空间分隔:

用户架构

<?xml version="1.0" encoding="utf-8"?>
<xs:schema
    targetNamespace="urn:company:schema:xsd:users"
    elementFormDefault="qualified"
    xmlns:cd="urn:company:schema:xsd:commondata"
    xmlns:pfl="urn:company:schema:xsd:profile"
    xmlns:usr="urn:company:schema:xsd:users"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    version="1.0">
    <xs:import namespace="urn:company:schema:xsd:commondata" schemaLocation="company-common-data-schema-1.0.xsd" />
    <xs:import namespace="urn:company:schema:xsd:profile" schemaLocation="company-profile-schema-1.0.xsd" />
    <xs:annotation>
        <xs:documentation>
            Document Identifier: company-user-schema-1.0
            Revision history:
            V1.0
                Initial Schema
        </xs:documentation>
    </xs:annotation>
    <xs:element name="Users">
        <xs:complexType>
            <xs:sequence minOccurs="1" maxOccurs="unbounded">
                <xs:element name="User" type="usr:UserType" />
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:complexType name="UserType">
        <xs:choice>
            <xs:element name="EmailAddress" type="cd:EmailAddressType" />
            <xs:element name="Active" type="xs:boolean" default="false" />
            <xs:element name="Profile" type="pfl:ProfileType" minOccurs="0" />
        </xs:choice>
    </xs:complexType>
</xs:schema>

个人资料架构

<?xml version="1.0" encoding="utf-8"?>
<xs:schema
    targetNamespace="urn:company:schema:xsd:profile"
    elementFormDefault="qualified"
    xmlns:pfl="urn:company:schema:xsd:profile"
    xmlns:cd="urn:company:schema:xsd:commondata"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    version="1.0">
    <xs:import namespace="urn:company:schema:xsd:commondata" schemaLocation="company-common-data-schema-1.0.xsd" />
    <xs:annotation>
        <xs:documentation>
            Document Identifier: company-profile-schema-1.0
            Revision history:
            V1.0
                Initial Standard
        </xs:documentation>
    </xs:annotation>
    <xs:complexType name="ProfileType">
        <xs:choice>
            <xs:element name="FirstName" type="cd:NameType" />
            <xs:element name="LastName" type="cd:NameType" />
            <!-- remove other elements for brevity -->
        </xs:choice>
    </xs:complexType>
</xs:schema>

通用数据架构

<?xml version="1.0" encoding="utf-8"?>
<xs:schema
    targetNamespace="urn:company:schema:xsd:commondata"
    elementFormDefault="qualified"
    xmlns:cdt="urn:company:schema:xsd:commondata"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    version="1.0">
    <xs:annotation>
        <xs:documentation>
            Document Identifier: company-common-datatype-schema-1.0
            Revision history:
            V1.0
                Initial Schema
        </xs:documentation>
    </xs:annotation>
    <xs:simpleType name="EmailAddressType">
        <xs:restriction base="xs:token">
            <xs:maxLength value="254"/>
            <xs:pattern value="[_\-a-zA-Z0-9'\.\+]+@[a-zA-Z0-9](\.?[\-a-zA-Z0-9]*[a-zA-Z0-9])*"/>
        </xs:restriction>
    </xs:simpleType>
    <xs:simpleType name="NameType">
        <xs:restriction base="xs:token">
            <xs:maxLength value="100"/>
            <xs:pattern value="[A-Za-z]+((\s)?((\'|\-|\.)?([A-Za-z])+))*" />
        </xs:restriction>
    </xs:simpleType>
</xs:schema>

注意:我正在将这些架构添加到资源中。

以下是我要验证的XML:

XML符合架构

<?xml version="1.0" encoding="utf-8"?>
<usr:Users>
    <usr:User>
        <usr:EmailAddress>john.doe@company.com</usr:EmailAddress>
        <usr:Active>true</usr:Active>
        <pfl:Profile>
            <pfl:FirstName>John</pfl:FirstName>
            <pfl:LastName>Doe</pfl:LastName>
        </pfl:Profile>
    </usr:User>
</usr:Users>

不符合架构的XML

<?xml version="1.0" encoding="utf-8"?>
<Foos>
    <Foo>
        <FooEmail>john.doe@company.com</FooEmail>
        <FooActive>true</FooActive>
        <FooProfile>
            <FooFirstName>John</FooFirstName>
            <FooLastName>Doe</FooLastName>
        </FooProfile>
    </Foo>
</Foos>

以下是我用来根据我的架构验证XML的代码:

// remove some of the codes for brevity
private static bool ValidateXml(string xmlSrc, XmlReaderSettings xrs, out IList<Tuple<object, Exception>> validationErrors)
{
    var isValid = false;
    var xmlReader = new object();

    validationErrors = new List<Tuple<object, Exception>>();

    try
    {
        using (var xtr = new XmlTextReader(xmlSrc))
        using (var xr = XmlReader.Create(xtr, xrs))
        {
            while (xr.Read()) { }
            xmlReader = xr;
        }

        isValid = true;
    }
    catch (Exception xdsEx)
    {

        validationErrors.Add(
            new Tuple<object, Exception>(xmlReader, xdsEx));
    }
    return isValid;
}



private static XmlReaderSettings XmlSchemaReader(
    IEnumerable<string> xmlSchemas,
    out IList<Tuple<object, XmlSchemaException>> validationErrors)
{

    var schemaCollection = new XmlSchemaSet();
    var readerSettings = InitializeDefaultXmlReaderSettings();
    var internalValidationErrors = new List<Tuple<object, XmlSchemaException>>();

    foreach (var xmlSchema in xmlSchemas)
    {
        var iterationValidationErrors = new List<Tuple<object, XmlSchemaException>>();

        var xsdReader = new StringReader(xmlSchema);
        var schema = XmlSchema.Read(xsdReader,
        (obj, eventArgs) => iterationValidationErrors.Add(
            new Tuple<object, XmlSchemaException>(obj, eventArgs.Exception)));

        readerSettings.Schemas.Add(schema);
        internalValidationErrors.AddRange(iterationValidationErrors);
    }
    validationErrors = internalValidationErrors;

    return readerSettings;
}

private static XmlReaderSettings InitializeDefaultXmlReaderSettings()
{
    var readerSettings = new XmlReaderSettings();

    readerSettings.ValidationType = ValidationType.Schema;
    readerSettings.ValidationFlags |= XmlSchemaValidationFlags.AllowXmlAttributes;
    readerSettings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema;
    readerSettings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
    readerSettings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;

    return readerSettings;
}

我做错了什么?它正在使用第一个给定的XML示例。

0 个答案:

没有答案