19

XSDは次のとおりです。

<?xml version="1.0"?>
<xsd:schema 
elementFormDefault='unqualified' 
attributeFormDefault='unqualified' 
xmlns:xsd='http://www.w3.org/2001/XMLSchema' 
>

  <xsd:simpleType name='TheSimpleType'>
    <xsd:restriction base='xsd:string' />
  </xsd:simpleType>
</xsd:schema>

上記のものを含む2番目のXSDは次のとおりです。

<?xml version="1.0" encoding="UTF-8" ?>
<xsd:schema 
elementFormDefault='unqualified' 
attributeFormDefault='unqualified' 
xmlns:xsd='http://www.w3.org/2001/XMLSchema' 
targetNamespace='a'
xmlns='a'
>

  <xsd:include schemaLocation='Include.xsd' />

  <xsd:element name = "TheElement" >
  <xsd:complexType>
  <xsd:attribute name="Code" type="TheSimpleType" use="required"/>
  </xsd:complexType>
  </xsd:element>
</xsd:schema>

(2番目の)XSDをC#に読み込む必要があります。

  1. 有効なXSDであることを確認し、
  2. それに対してドキュメントを検証します。

スキーマで読み取るC#は次のとおりです。

    XmlSchemaSet schemaSet = new XmlSchemaSet();
    foreach (string sd in Schemas)
    {
        using (XmlReader r = XmlReader.Create(new FileStream(sd, FileMode.Open)))
        {
            schemaSet.Add(XmlSchema.Read(r, null));
        }
    }
    schemaSet.CompilationSettings = new XmlSchemaCompilationSettings();
    schemaSet.Compile();

「Type'a:TheSimpleType'が宣言されていないか、単純な型ではない」ため、.Compile()は失敗します。

ただし、次のいずれかの場合に機能します。

  • 名前空間がスキーマから削除されている、または
  • 名前空間がインクルードに追加されます。

問題は、スキーマを編集せずにC#でそれを受け入れるにはどうすればよいですか?

問題は、両方のスキーマをXmlSchemaSetに入れましたが、一方が他方に含まれていること、つまり、それ自体ではうまくいかないことをC#に伝える必要があることだと思います。実際、XmlSchemaSetにメインXSD(インクルードではなく)(名前空間なし(または名前空間あり)の両方)についてのみ伝える場合、「タイプ'TheSimpleType'は宣言されていないか、単純なタイプではありません。」

したがって、これは解決に関する質問のようです:どのように?!

4

5 に答える 5

28

問題は、次の行で読み取るためにスキーマを開く方法にあります。

XmlReader.Create(new FileStream(sd, FileMode.Open)

インクルード ファイルへのパスがどのように解決されているかを確認する前に、独自XmlResolverのパスを作成する必要がありました。これは、親スキーマのディレクトリからではなく、実行可能ファイルのディレクトリからのものでした。問題は、親スキーマがその BaseURI セットを取得していないことです。スキーマを開く方法は次のとおりです。

XmlReader.Create(new FileStream(pathname, FileMode.Open, FileAccess.Read),null, pathname)
于 2012-04-16T17:42:06.457 に答える
1

これを試してください:D

public static XmlSchema LoadSchema(string pathname)
{
    XmlSchema s = null;
    XmlValidationHandler h = new XmlValidationHandler();
    using (XmlReader r = XmlReader.Create(new FileStream(pathname, FileMode.Open)))
    {
        s = XmlSchema.Read(r, new ValidationEventHandler(h.HandleValidationEvent));
    }

    if (h.Errors.Count > 0)
    {
        throw new Exception(string.Format("There were {1} errors reading the XSD at {0}. The first is: {2}.", pathname, h.Errors.Count, h.Errors[0]));
    }

    return s;
}

public static XmlSchema LoadSchemaAndResolveIncludes(string pathname)
{
    FileInfo f = new FileInfo(pathname);
    XmlSchema s = LoadSchema(f.FullName);

    foreach(XmlSchemaInclude i in s.Includes)
    {
        XmlSchema si = LoadSchema(f.Directory.FullName + @"\" + i.SchemaLocation);
        si.TargetNamespace = s.TargetNamespace;
        i.Schema = si;
    }

    return s;
}

public static List<ValidationEventArgs> Validate(string pathnameDocument, string pathnameSchema)
{
    XmlSchema s = LoadSchemaAndResolveIncludes(pathnameSchema);

    XmlValidationHandler h = new XmlValidationHandler();

    XmlDocument x = new XmlDocument();
    x.Load(pathnameDocument);
    x.Schemas.Add(s);
    s.Compile(new ValidationEventHandler(h.HandleValidationEvent));
    x.Validate(new ValidationEventHandler(h.HandleValidationEvent));
    return h.Errors;
}

特にに注意してくださいsi.TargetNamespace = s.TargetNamespace;

明らかに、これは、インクルードが、それらがインクルードされているスキーマに相対的なファイルパスとして指定されていることを前提としています。

于 2012-04-13T08:44:12.357 に答える