C#で System.Xml.XmlDocument を使っています。
XmlDocument xmlDocument = new XmlDocument();
プレフィックス付きのノードを作るとき、たとえば
<code>
<s:root xmlns:s="urn:hogehoge-hoge" >
<s:child />
</s:root>
</code>
というXMLを作りたいとして、
XmlNode root = xmlDocument.CreateNode(XmlNodeType.Element, "s", "root", "hogehoge-hoge");
XmlNode child = xmlDocument.CreateNode(XmlNodeType.Element, "s", "child", "hogehoge-hoge");
root.AppendChild(child);
とすると動きますが、毎回NamespaceURIを指定するのは変だと思います。
しかし、最後の引数を指定しないと、prefixが出力されません。
また、
xmlDocument.Save("filename");
でファイルに保存するのは1行ですが、string型で受け取ろうと思うと、
StringWriter writer = new StringWriter();
xmlDocument.Save(writer);
string output = writer.ToString();
としないといけません。
色々不便なので、XmlDocument
を継承したExtendedXmlDocument
を作りました。命名がSXGA並にださいですが。。
このクラス内部では、prefixとnamespaceURIのHashtableを持っていて、一度指定すると以降はnamespaceURIを指定しなくても対応するものを用意してくれます。
また、ToString()
をオーバーライドしてあるので、1行で文字列を受け取れます。
・・・と、ここまでは良かったんですが(前置きが長い)、その後調子に乗ってCreateAttribute()
をオーバーライドしたらはまりました。
public override XmlAttribute CreateAttribute(string prefix, string name, string value);
を作って、内部で
base.CreateAttribute(name);
を呼ぶと、StackOverflowExceptionが発生します。
どうやら、XmlDocument.CreateAttribute(string)
内部でCreateAttribute(string, string, string)
を呼んでいたみたいです。
C#のオーバーライドは動的にメソッドを呼んでくれるので、派生クラスのCreateAttribute(string, string, string)
が呼ばれてしまって、その内部で CreateAttribute(string)
を呼ぶと無限ループ、と。
.NET Frameworkの内部コードが見られれば一瞬で解決した問題なんですが。オーバーライドは慎重に使わないとバグの元ですね。オーバーロードと組み合わさるとたまに危険。気をつけます。
編集部注: その後.NET Frameworkがオープンソース化されましたね。当時は想像もつかなかったことでしょう。