5

XSDファイルに対してXMLファイルを検証するために使用する静的メソッドがあります。別の 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>

メイン.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 月 5 日更新:

舞台裏で何が起こっているかを確認するために、独自の 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})--> 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})--> TYPES.xsd へのファイルストリーム

私には良さそうです (最初の 2 つの呼び出しが等しいことを除いて!?!) - TYPES.XSD へのパスは、必要に応じて解決されます。

それにもかかわらず、xset.Compile()例外がスローされます:「タイプ MY_AMOUNT は宣言されていません」

そして、私には理由がわかりません:/

4

2 に答える 2

2

まず、xsd ファイルを有効にする必要があります。

Types.xsd (追加されたスキーマ ルート要素と 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 ファイルが同じディレクトリにあれば、スキーマは正常にコンパイルされます。

于 2016-12-05T10:59:42.347 に答える
1

このまったく同じ問題に遭遇しました。

これが正しい答えだと言っているわけではありませんEnvironment.CurrentDirectoryが、含まれている XSD が配置されているパスにプロパティを設定することで回避しました。その後、すべて正常に処理されました。

于 2017-10-06T06:31:55.937 に答える