メソッドから XML の有効性をテストするにはどうすればよいでしょうか?
-
02-07-2019 - |
質問
バインドに使用するために、サーバー アプリケーションから Web サイトのフロントエンドに情報を送信するために使用される WCF メソッドがいくつかあります。結果を、バインドするデータを含む XML ツリーのルートである XElement として送信します。
データを調べて、期待どおりの結果が得られることを確認するテストをいくつか作成したいと思います。
私の現在の考えは次のとおりです。XElement ツリーを返すすべてのメソッドには、対応するスキーマ (.XSD) ファイルがあります。このファイルは、WCF クラスを埋め込みリソースとして含むアセンブリ内に含まれています。
テストでは、これらのメソッドでメソッドを呼び出し、結果をこれらの埋め込みスキーマと比較します。
これは良いアイデアですか?そうでない場合、メソッドがどのような種類の XML を返すかを「保証」するために、他にどのような方法を使用できるでしょうか?
そうである場合、XElement をスキーマに対してどのように検証しますか?そして、そのスキーマが埋め込まれているアセンブリからそのスキーマを取得するにはどうすればよいでしょうか?
解決
xsd スキーマを使用して XML を検証することは良い考えだと思います。
ロードされたスキーマを使用して XElement を検証する方法:この例でわかるように、「スキーマ検証後の情報セット」を取得するには、最初に XDocument を検証する必要があります (XDOcument の Validate メソッドを使用せずにこれを行う解決策があるかもしれませんが、私はまだ見つけていません)。
String xsd =
@"<xsd:schema xmlns:xsd='http://www.w3.org/2001/XMLSchema'>
<xsd:element name='root'>
<xsd:complexType>
<xsd:sequence>
<xsd:element name='child1' minOccurs='1' maxOccurs='1'>
<xsd:complexType>
<xsd:sequence>
<xsd:element name='grandchild1' minOccurs='1' maxOccurs='1'/>
<xsd:element name='grandchild2' minOccurs='1' maxOccurs='2'/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>";
String xml = @"<?xml version='1.0'?>
<root>
<child1>
<grandchild1>alpha</grandchild1>
<grandchild2>beta</grandchild2>
</child1>
</root>";
XmlSchemaSet schemas = new XmlSchemaSet();
schemas.Add("", XmlReader.Create(new StringReader(xsd)));
XDocument doc = XDocument.Load(XmlReader.Create(new StringReader(xml)));
Boolean errors = false;
doc.Validate(schemas, (sender, e) =>
{
Console.WriteLine(e.Message);
errors = true;
}, true);
errors = false;
XElement child = doc.Element("root").Element("child1");
child.Validate(child.GetSchemaInfo().SchemaElement, schemas, (sender, e) =>
{
Console.WriteLine(e.Message);
errors = true;
});
アセンブリから埋め込みスキーマを読み取り、それを XmlSchemaSet に追加する方法:
Assembly assembly = Assembly.GetExecutingAssembly();
// you can use reflector to get the full namespace of your embedded resource here
Stream stream = assembly.GetManifestResourceStream("AssemblyRootNamespace.Resources.XMLSchema.xsd");
XmlSchemaSet schemas = new XmlSchemaSet();
schemas.Add(null, XmlReader.Create(stream));
他のヒント
軽量の作業を行っていて XSD が過剰な場合は、XML データを強力に型指定することも検討してください。たとえば、プロジェクトには XElement から派生したクラスが多数あります。1 つは ExceptionXElement、もう 1 つは HttpHeaderXElement などです。その中で、XElement から継承し、インスタンスの作成元となる XML データを含む文字列を取得する Parse メソッドと TryParse メソッドを追加します。TryParse() が false を返す場合、文字列は期待する XML データに準拠していません (ルート要素の名前が間違っている、子要素が欠落しているなど)。
例えば:
public class MyXElement : XElement
{
public MyXElement(XElement element)
: base(element)
{ }
public static bool TryParse(string xml, out MyXElement myElement)
{
XElement xmlAsXElement;
try
{
xmlAsXElement = XElement.Parse(xml);
}
catch (XmlException)
{
myElement = null;
return false;
}
// Use LINQ to check if xmlAsElement has correct nodes...
}