包含XSD文件的编译模式



我有静态方法,我用它来验证XML文件针对XSD文件。这正常工作,直到有一个XSD文件包含另一个XSD文件。

示例,我遇到麻烦的地方:

types.xsd:

<xs:simpleType name="MY_AMOUNT">
    <xs:restriction base="xs:decimal">
        <xs:maxInclusive value="999999999999.99"/>
        <xs:minInclusive value="-999999999999.99"/>
        <xs:totalDigits value="14"/>
        <xs:fractionDigits value="2"/>
    </xs:restriction>
</xs:simpleType>

main.xsd:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
    <xs:include schemaLocation="TYPES.xsd"/>
    <xs:element name="ROOT">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="SOMEREF1"/>
                <xs:element ref="SOMEREF2"/>
                <xs:element name="AMOUNT" type="MY_AMOUNT" minOccurs="0"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

验证代码:

public static class XmlUtils
{
    private static string Errors = string.Empty;
    public static bool ValidateAgainstXSD(string xmlFilePath, string xsdFilePath, ref string message)
    {
        try
        {
            var settings = new XmlReaderSettings();
            settings.ValidationType = ValidationType.Schema;
            settings.ValidationFlags = XmlSchemaValidationFlags.ProcessInlineSchema
                | XmlSchemaValidationFlags.ProcessInlineSchema
                | XmlSchemaValidationFlags.ReportValidationWarnings;
            settings.Schemas.Add(null, xsdFilePath);
            settings.Schemas.Compile();
            settings.ValidationEventHandler += (sender, args) =>
            {
                if (args.Severity == XmlSeverityType.Error)
                {
                    Errors += args.Message + "n";
                }
            };
            using (var reader = XmlReader.Create(xmlFilePath, settings))
            {
                while (reader.Read()) { }
            }
            message = Errors ?? string.Empty;
            return string.IsNullOrEmpty(Errors);
        }
        catch (Exception e)
        {
            message = "# error validating xml file: " + e.Message;
            return false;
        }
    }
}

某种程度上看来我必须指定随附的XSD文件的路径,但我不知道在哪里。

错误发生在settings.Schemas.Compile();上,其中说" my_amount"类型没有声明。我读过有关自定义XMLResolvers的信息,但老实说我没有工作。

如果这对于答案很重要:XSD文件始终位于同一目录中!

该方法称为以下方式:

string msg = string.Empty;
string basedir = @"C:Temp";
string xml = Path.Combine(basedir, "XML_FILE.xml");
string xsd = Path.Combine(basedir, "MAIN.xsd");
if (XmlUtils.ValidateAgainstXSD(xml, xsd, ref msg))
{
    // do some work
}
else
{
    Console.WriteLine(msg);
}
Console.ReadLine();

任何帮助都非常感谢 - 谢谢!

更新2016-12-05:

我写了自己的Xmlurlresolver,看看幕后发生了什么:

internal class XUrlResolver : XmlUrlResolver
{
    public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn)
    {
        return base.GetEntity(absoluteUri, role, ofObjectToReturn);
    }
    public override Uri ResolveUri(Uri baseUri, string relativeUri)
    {
        return base.ResolveUri(baseUri, relativeUri);
    }
}

我只是尝试做:

XmlSchemaSet xset = new XmlSchemaSet();
xset.XmlResolver = new XUrlResolver();
xset.Add("", xsdFilePath);
xset.Compile();

现在发生了什么(在xset.Add上):

  1. XmlUrlResolver.ResolveUri(null,"C:\Temp\MAIN.XSD")-> {file:///C:/Temp/MAIN.xsd}
  2. XmlUrlResolver.ResolveUri(null,"C:\Temp\MAIN.XSD")-> {file:///C:/Temp/MAIN.xsd}
  3. XmlUrlResolver.GetEntity({file:///C:/Temp/MAIN.xsd})-> fileStream to main.xsd
  4. XmlUrlResolver.ResolveUri({file:///C:/Temp/MAIN.xsd},"TYPES.XSD")-> {file:///C:/Temp/TYPES.xsd}
  5. XmlUrlResolver.GetEntity({file:///C:/Temp/TYPES.xsd})-> fileStream toge.xsd

对我来说看起来不错(除了前两个呼叫相等!?!) - type.xsd的路径。

尽管如此, xset.Compile()抛出了一个例外:"键入my_amount未声明"

我不知道为什么:/

首先,您需要使XSD文件有效。

types.xsd(添加了架构root元素和xs名称空间)

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:simpleType name="MY_AMOUNT">
    <xs:restriction base="xs:decimal">
        <xs:maxInclusive value="999999999999.99"/>
        <xs:minInclusive value="-999999999999.99"/>
        <xs:totalDigits value="14"/>
        <xs:fractionDigits value="2"/>
    </xs:restriction>
</xs:simpleType>
</xs:schema>

main.xsd(删除了无效的参考)。

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
    <xs:include schemaLocation="TYPES.xsd"/>
    <xs:element name="ROOT">
        <xs:complexType>
            <xs:sequence>                
                <xs:element name="AMOUNT" type="MY_AMOUNT" minOccurs="0"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

之后,鉴于两个XSD文件都在同一目录中,您的模式将罚款。

我遇到了同样的问题。

我并不是建议这是正确的答案,但是我将Environment.CurrentDirectory属性设置为所包含XSD的路径来解决它。然后所有处理都很好。

最新更新