2009-04-03 9 views
4

xmlの下にあるフォーム要素であるxml 'snippets'を使って作業しています。私はスキーマを持っていますが、完全なxmlドキュメントではないため、これらのファイルを検証することはできません。これらのスニペットは、他のツールで使用されているときに有効なxmlを形成するために必要な親要素でラップされているため、有効なxmlまたはスキーマの変更に多くのオプションがありません。文書全体ではなくxmlノードを検証する

ドキュメント全体ではなく、要素を検証することは可能ですか? そうでない場合は、どのような回避策を提案できますか?

私はC#.NET 2.0フレームワークで作業しています。

+0

'XmlDocument'のルートノードを使用できない場合は' SelectSingleNode'を使用することができません.Xmlをロードする必要があります。これは、有効でない場合に失敗します。あなた自身の文書が有効でない限り、 'XPath'を使うことはできないと思います。 そうする方法はありますか? –

答えて

4

私はXML文書の一部だけを検証できる同様の問題がありました。私は内側に埋め込まれたリソースのXSDから読み込む基本的に

private void ValidateSubnode(XmlNode node, XmlSchema schema) 
{ 
    XmlTextReader reader = new XmlTextReader(node.OuterXml, XmlNodeType.Element, null); 

    XmlReaderSettings settings = new XmlReaderSettings(); 
    settings.ConformanceLevel = ConformanceLevel.Fragment; 
    settings.Schemas.Add(schema); 
    settings.ValidationType = ValidationType.Schema; 
    settings.ValidationEventHandler += new ValidationEventHandler(XSDValidationEventHandler); 

    using (XmlReader validationReader = XmlReader.Create(reader, settings)) 
    {  
     while (validationReader.Read()) 
     { 
     } 
    } 
} 

private void XSDValidationEventHandler(object sender, ValidationEventArgs args) 
{ 
    errors.AppendFormat("XSD - Severity {0} - {1}", 
         args.Severity.ToString(), args.Message); 
} 

が、私はそれを(私は.SelectSingleNodeによって全体のXmlDocumentから選択)のXmlNodeを渡し、XMLスキーマ:私はここで、この方法を思い付きました私のアプリ。発生する可能性のある検証エラーは「エラー」文字列ビルダーに詰め込まれ、最後に読み込まれてエラーが記録されているかどうかが確認されます。私にとって

ワークス - 私は同じ問題を抱えていた

+0

このソリューションは非常にうまく動作します。実際、これは私が文書のために現在行っている検証と著しく似ています。私は個々のノードにも適用できるかどうかはわかりませんでした。振り返ると、ルートはそれ自身のノードだと思います。 – ipwnponies

+0

ありがとう、マーク!これは私にも多くの助けとなりました。 – Kizz

+0

Marc、この答えを 'XmlTextReader'を使わないように編集し、' using'ブロックを使うこともできますか?私はちょうどこのコードコピー/ペーストを見た。 –

0

特別な名前空間エイリアスを使用して、検証する要素を評価し、その名前空間エイリアスのスキーマのみを追加できますが、他のものは追加できません。こうすることで、特別な名前空間接頭辞を持つ要素だけが検証されます。

+0

私が理解していることから、これはスキーマの編集/作成に必要なので適切ではありません。私はスキーマを変更することができません。これは、毎年他の人が使用し更新するプロトコルなので、変更することはできません。私は内部ツールを作成するだけなので、メンテナンスは最小限に抑える必要があります。 – ipwnponies

2

XmlDocument.Validateメソッドがあり、引数としてXmlNodeを受け取り、このノードのみを検証します。それはあなたが探しているものかもしれません...

+0

残念ながら、私は今のところプロジェクトにアクセスすることができないので、これを確認することはできません。しかし、MSDNを読んで、これは私が探していたものと思われます。すべての今回、私はXmlSchemaの下で探しています... – ipwnponies

+0

これは動作しません。検証されるべきノードは、正しい「深さ」になければならない。このメソッドは、XMLファイルを部分的に検証したい場合に便利です。私は最初に有効なXMLファイルがありません。 – ipwnponies

0

私がしたいことはできないようです。私の現在の回避策は、空白のテンプレートXML文書を作成することです。次に、目的の要素をスニペットに置き換えます。そこから、私はValidateメソッドが実行可能であると信じています。しかし、このテンプレートを動的に作成することは、別の大変な作業であるようです。 「スケルトン」文書を作成する簡単な方法はないようです。

rootとしてスニペットの要素を持つ新しいスキーマにXSLT変換を使用してスキーマファイルを変換できます。

+0

私は、XSLTが役に立つかもしれないと思います。いくつかの提案について私の新しい答えを見てください – MartinStettner

1

[OK]を、ここでは別のアプローチです。あなたが検証したいタイプNestedElementのスニペットを持って、あなたの元のスキーマが

<xs:schema id="MySchema" xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
    <xs:element name="RootElement"> 
    <xs:complexType> 
     <xs:sequence> 
     <xs:element name="NestedElement"> 
      <xs:complexType> 
      <xs:attribute name="Name" type="xs:string" use="required"/> 
      </xs:complexType> 
     </xs:element> 
     </xs:sequence> 
    </xs:complexType> 
    </xs:element> 
</xs:schema> 

だろうと言う:

<NestedElement Name1="Name1" /> 

次にあなたが作成する

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="xs:element[@name='NestedElement']" 
       xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
    <xs:schema id="MySchema"> 
     <xsl:copy-of select="."/> 
    </xs:schema> 
    </xsl:template> 
</xsl:stylesheet> 

のようなXSLTテンプレートを使用することができますNestedElementをルートとする新しいスキーマ得られたスキーマは、あなたが次に

XmlSchema schema; 
using (MemoryStream stream = new MemoryStream()) 
using (FileStream fs = new FileStream("MySchema.xsd", FileMode.Open)) 
using(XmlReader reader = XmlReader.Create(fs)) { 
    XslCompiledTransform transform = new XslCompiledTransform(); 
    transform.Load("SchemaTransform.xslt"); 
    transform.Transform(reader, null, stream); 
    stream.Seek(0, SeekOrigin.Begin); 
    schema = XmlSchema.Read(stream, null); 
} 
XmlDocument doc = new XmlDocument(); 
doc.Schemas.Add(schema); 
doc.Load("rootelement.xml"); 
doc.Validate(ValidationHandler); 

MySchema.xsdようなコードを使用して、この新しいスキーマに対してスニペット文書を検証でき

<xs:schema id="MySchema" xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
    <xs:element name="NestedElement"> 
    <xs:complexType> 
     <xs:attribute name="Name" type="xs:string" use="required" /> 
    </xs:complexType> 
    </xs:element> 
</xs:schema> 

ようになり、元のスキーマ、SchemaTransform.xsltである(上記のように)変換でありますrootelement.xmlは、単一のスニペットノードを含むXMLドキュメントです。

+0

これは非常にエレガントな解決策です。しかし、私がそれを使わないようにする一つのことがあります。この変換では、 'NestedElement'の知識を知る必要があります。これは、第三者によるスキーマの更新があり、xsltの更新/保守が必要になるため、問題です。 – ipwnponies

+0

要素名(「NestedElememt」)をパラメータにして、コード内のスニペットの最上位要素から読み取ることができます。次に、複数のスニペット要素でも動作します。 – MartinStettner

+0

時間がある場合は、おそらく "摂食"パラメータトリックを示すことができます。私は文字通りこれに3-4時間を無駄にし、どこにも行きませんでした。実際には、パラメータを入力するのは簡単ですが、トリックはXSLT 1.0で使用することです:http://stackoverflow.com/questions/6117460/xsl-how-to-use-parameter-inside-matchテンプレートは私が望むものに決して合わなかった。これはばかげているので、今のところすべてを置き換えてください。しかし解決のために+1。 –

0

:-)あなたの走行距離は異なる場合があります。解決のためにここでも尋ねられました。私は回避策を見つけました。

問題は、ルート要素のみを検証できることです。だから... ...私は、メモリ内のスキームを編集して、ルート

public static void AddElementToSchema(XmlSchema xmlSchema, string elementName, string elementType, string xmlNamespace) 
{ 
    XmlSchemaElement testNode = new XmlSchemaElement(); 
    testNode.Name = elementName; 
    testNode.Namespaces.Add("", xmlNamespace); 
    testNode.SchemaTypeName = new XmlQualifiedName(elementType, xmlNamespace); 
    xmlSchema.Items.Add(testNode); 
    xmlSchema.Compile(XMLValidationEventHandler); 
} 

に検証する要素/タイプを追加ラインだけのカップル、あなたは任意のXSDファイルを変更したり、追加してはいけません:)にこの単純な変更でメモリ内のスキーマを使用すると、完全なドキュメントの検証に使用するコードと同じコードでフラグメントを検証できます。検証するフラグメントのルート要素に名前空間が含まれていることを確認してください。 :)

関連する問題