15
19

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

C#とXPathで名前空間を無視してXMLを解析する

Last updated at Posted at 2016-08-03

XDocumentという便利なXML操作用のクラスがあります。このクラスは通常ではXPathによる検索、解析用の機能はありません。

ところが、System.Xml.XPathをusingするとXPath用の拡張メソッドが使えます。とても便利です。これでXPathで楽に要素の取得ができます。

//XDocumentでXPath用の拡張メソッドを使うのに必要
using System.Xml.XPath;

しかし、XMLが名前空間付きの場合、面倒な問題があります。いちいち名前空間(namespace)を指定しないといけないのです。

名前空間を指定する場合

//XML文字列からXDocumentオブジェクトを生成
var doc = XDocument.Load(new StringReader(xmlString));

//名前空間のための処理
string nameSpace = "http://example.com";
var nsmgr = new XmlNamespaceManager(new NameTable());
nsmgr.AddNamespace("ns", nameSpace);

//名前空間を指定して検索
var nodeD = doc.XPathSelectElement("ns:nodeA/ns:nodeB/ns:nodeC/ns:nodeD", nsmgr);

XmlNamespaceManagerを作り、XPathSelectElementを呼び出す度にこれを渡さないといけません。それだけならまだいいのですが、XPathの指定で毎回ns:を付けるのが非常に面倒だし可読性も悪いです。

名前空間を無視して検索する

以上のように名前空間を指定すると色々面倒です。
この問題の解決策として、名前空間を無視して解析する方法が以下です。

//XML文字列からXDocumentオブジェクトを生成
var doc = XDocument.Load(new StringReader(xmlString));

//各ノードのNameを名前空間なしの要素名にする
foreach(var e in doc.Descendants()) e.Name = e.Name.LocalName;

//上記処理により、検索時に名前空間の指定が不要
var nodeD = doc.XPathSelectElement("nodeA/nodeB/nodeC/nodeD");

無理矢理な感じですが、動いているので多分大丈夫でしょう。
これですっきり!

15
19
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
19

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?