XSD验证不失败,尾随换行符



Xml验证不是我必须接触的东西,所以可能有一些愚蠢的东西我错过了,到目前为止,我没有成功地在谷歌上寻求任何帮助。我的问题是,我有一个类型的限制,说它只能是字母或空格。带有前导换行符的元素不通过验证,但带有尾随换行符的元素通过验证。如何使尾随换行符失败?

我创建了一个简化的测试用例,如下所示:

验证代码:

public List<XsdValidationError> ValidateXmlAgainstXsd(String xml, String xsdFilePath, Boolean processSchemaLocation = false)
{
    var ret = new List<XsdValidationError>();
    var xss = new XmlSchemaSet();
    var xmlUrlResolver = new XmlUrlResolver();
    xmlUrlResolver.CachePolicy = new RequestCachePolicy(RequestCacheLevel.Default);
    xss.XmlResolver = xmlUrlResolver;
    var xsdXElement = XElement.Parse(File.ReadAllText(xsdFilePath));
    var targetNamespaceAttribute = xsdXElement.Attribute("targetNamespace");
    xss.Add(targetNamespaceAttribute != null ? targetNamespaceAttribute.Value : "", xsdFilePath);

    var settings = new XmlReaderSettings();
    settings.ValidationType = ValidationType.Schema;
    settings.Schemas = xss;
    settings.ValidationFlags = XmlSchemaValidationFlags.ProcessInlineSchema;
    if (processSchemaLocation)
        settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
    settings.ValidationEventHandler += (sender, e) =>
        {
            var xve = new XsdValidationError { Message = e.Message, LineNumber = e.Exception.LineNumber, LinePosition = e.Exception.LinePosition };
            ret.Add(xve);
        };
    using (var sr = new StringReader(xml))
    {
        var xr = XmlReader.Create(sr, settings);
        while (xr.Read());
        return ret;
    }
}
public class XsdValidationError
{
    public String Message { get; set; }
    public int LineNumber { get; set; }
    public int LinePosition { get; set; }
    public override string ToString()
    {
        return String.Format("Line {0:n0}, Position {1:n0}: {2}", this.LineNumber, this.LinePosition, this.Message);
    }
}

输入XML和XSD:

<People>
    <Person>Hello Person One
</Person>
    <Person>Hello Person Two</Person>
    <Person>
Hello Person Three</Person>
</People>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="People">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="Person" maxOccurs="unbounded">
                    <xs:simpleType>
                        <xs:restriction base="xs:string">
                            <xs:pattern value="[a-zA-Z ]+"/>
                        </xs:restriction>
                    </xs:simpleType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

在XML中,第一人没有失败,第二个人通过了,第三个人失败了。我需要一个也失败的人。

不能更改输入XML或XSD。Visual Studio正确地验证该文件。什么好主意吗?

我认为这是微软XSD解析器的一个怪癖/bug。string类型的定义是:-

 <xsd:simpleType name="string" id="string">
   <xsd:restriction base="xsd:anySimpleType">
   <xsd:whiteSpace value="preserve"/>
   </xsd:restriction>
 </xsd:simpleType>

由于空白面被设置为'保留',它应该包含元素中的所有内容,空白和所有。

然而,正如你所注意到的,它忽略了末尾的空格。似乎除了在代码中手动应用验证规则之外,对此您可以做的事情不多。

偶然地,它在Xerces中按照预期进行验证(前导和尾随空格都出错)。

我发现,如果我切换到使用XmlDocument来加载xml,那么它会正确验证,但是我丢失了行号信息。我不确定在引擎盖下发生了什么,但更改为此将在我的情况下正确验证。

var xd = new XmlDocument();
xd.LoadXml(xml);
var xr = XmlReader.Create(new XmlNodeReader(xd), settings);

最新更新