雑記 |
Visual Basic 中学校 > 雑記 >
2020/5/22
この記事が対象とする製品・バージョン
![]() |
Visual Studio 2019 | ◎ | 対象です。 |
![]() |
Visual Studio 2017 | ◎ | 対象です。 |
![]() |
Visual Studio 2015 | ◎ | 対象です。 |
![]() |
Visual Studio 2013 | ◎ | 対象です。 |
![]() |
Visual Studio 2012 | ◎ | 対象です。 |
![]() |
Visual Studio 2010 | ◎ | 対象です。 |
![]() |
Visual Studio 2008 | ○ | 対象ですが、一部サンプルプログラムはサンプル中で使用しているXML以外の機能が原因で動作しません。 |
![]() |
Visual Studio 2005 | ○ | 対象ですが、一部サンプルプログラムはサンプル中で使用しているXML以外の機能が原因で動作しません。 |
![]() |
Visual Studio 2003 | ○ | 対象ですが、多くのサンプルプログラムはサンプル中で使用しているXML以外の機能が原因で動作しません。 |
![]() |
Visual Studio (2002) | × | 対象外です。 |
目次
この記事ではVB/C#でXMLを読み込む方法を説明します。
VB/C#でXMLを読み込んで処理をするには大きく分けて4つのアプローチがあります。
この記事では1・2・3のアプローチを扱います。3はさらに2つの方法に分けて扱います。簡単な使い分けは次の通りです。
(4のLINQ to XMLは洗練されていて便利ですが別の記事で説明します。)
アプローチ | 適しているケース | |
---|---|---|
1.VB/C#のクラスにマッピングする | ・XMLの構造が事前にわかっている。 ・XMLの中にあるたくさんの値を読み込む必要がある。 |
|
2.XPathで位置を指定して値を取り出す | ・XMLの構造が事前にわかっている。 ・XMLの中から取り出したい値は多くない。 |
|
3.先頭から順次読み込む | XmlDocumentを使う方法 | ・XMLの構造が事前にわかっていない。 ・難しいプログラムを扱いたくない。 |
XmlReaderを使う方法 | ・XMLの構造が事前にわかっていない。 ・XMLのサイズが巨大 ・パフォーマンスが重要 ・難しいプログラムを扱っても良い。 |
|
4.クエリ(LINQ to XML)を使って値を取り出す | ・XMLの構造が事前にわかっている。 ・条件をつけて抽出したり、並び替えたり、集計したりする。 |
■表:XMLを読み込むアプローチの使い分け
知識がなさ過ぎてよくわからない場合は、アプローチ1から順番に試してみて、合わないと思ったら次のアプローチを試してみてください。
参考
Effective XML Part1: Choose the right API (効果的なXML 第1回:正しいAPIの選択)
https://docs.microsoft.com/ja-jp/archive/blogs/xmlteam/effective-xml-part-1-choose-the-right-api
この記事では題材として次の2つのサンプルXMLを読み込む場合を考えます。
サンプル1:シンプルなXML
<?xml
version="1.0"
encoding="utf-8"
?> <history> <location>日本</location> <era name="奈良時代" start="710" end="794"> <person name="坂上田村麻呂"> <image>https://xxxxxx/x1.jpg</image> <note>征夷大将軍</note> </person> </era> <era name="平安時代" start="794" end="1185"> <person name="藤原道長"> <note>摂政。藤原家の摂関政治の絶頂。</note> </person> <person name="清少納言"> <note>枕草子</note> </person> </era> </history> |
サンプル1は個人や企業で使用する独自のXMLを想定しており、XMLの要素と属性だけを使用したシンプルな構造です。
サンプル1の特徴
・属性で値が指定されているもの(「奈良時代」や「710」など)と要素の内容として値が指定されているもの(「日本」や「征夷大将軍」など)があります。
・era要素とperson要素は複数出現します。(プログラムで読み込むとコレクションか配列で表現されることになります。)
・XML名前空間(xmlns)が使用されていません。
サンプル2:名前空間のあるXML
<?xml
version="1.0"
standalone="yes"?> <parent xmlns="http://example.org" xmlns:svg="http://www.w3.org/2000/svg"> <!-- parent contents here --> <svg:svg width="4cm" height="8cm" version="1.1"> <svg:ellipse cx="2cm" cy="4cm" rx="2cm" ry="1cm" /> </svg:svg> </parent> |
サンプル2は規格としてある程度共通で定義されているXMLを想定しています。この例はグラフィックスをXMLで表現する規格であるSVGです。
サンプル2の特徴
・XML名前空間(xmlns)が使用されています。
・コメントがあります。
VBの場合、 この記事で紹介する例はプログラムの冒頭で以下のImports文が記述されていることが前提です。
Imports System.Xml.Serialization
Imports System.Xml
C#の場合、 この記事で紹介する例はプログラムの冒頭で以下のUsing文が記述されていることが前提です。
using System.Xml.Serialization;
using System.Xml;
このほかに、状況によっては追加のImportsまたはusingが必要な場合があります。
XMLの定義があらかじめわかっている場合はVB/C#で同じ構造のクラスを作成しておくと、そのクラスに値を割り当てることができます。クラスを定義するコツは後述します。
このアプローチの良い点はXMLとロジックを疎結合にしやすい点です。クラスに値が割り当てられた後は完全にVB/C#の世界の話になってXMLを意識しなくてよくなります。
サンプル1のXMLの内容をVB/C#で定義したクラスにマッピングして読み込む例を以下に示します。
読み込みの実行にはXmlSerializerクラスのDesrializeメソッドを使用します。XmlSerializerクラスのコンストラクターでマッピング先の型を指定します。
VB
Public Class
history Public Property location As String <XmlElement("era")> Public Property era As List(Of era) End Class Public Class era <XmlElement("person")> Public Property person As person() <XmlAttribute> Public Property name As String <XmlAttribute> Public Property start As Integer <XmlAttribute> Public Property [end] As Integer End Class Public Class person Public Property image As String Public Property note As String <XmlAttribute> Public Property name As String End Class Private Function LoadXmlSample1Text() As String Dim xml As New System.Text.StringBuilder xml.AppendLine("<?xml version=""1.0"" encoding=""utf-8"" ?>") xml.AppendLine("<history>") xml.AppendLine(" <location>日本</location>") xml.AppendLine(" <era name=""奈良時代"" start=""710"" end=""794"">") xml.AppendLine(" <person name=""坂上田村麻呂"">") xml.AppendLine(" <image>https://xxxxxx/x1.jpg</image>") xml.AppendLine(" <note>征夷大将軍</note>") xml.AppendLine(" </person>") xml.AppendLine(" </era>") xml.AppendLine(" <era name=""平安時代"" start=""794"" end=""1185"">") xml.AppendLine(" <person name=""藤原道長"">") xml.AppendLine(" <note>摂政。藤原家の摂関政治の絶頂。</note>") xml.AppendLine(" </person>") xml.AppendLine(" <person name=""清少納言"">") xml.AppendLine(" <note>枕草子</note>") xml.AppendLine(" </person>") xml.AppendLine(" </era>") xml.AppendLine("</history>") Return xml.ToString End Function Private Function TestXml() As history Dim xmlText As String = Me.LoadXmlSample1Text Dim deserializer As New XmlSerializer(GetType(history)) Using stream As New MemoryStream(System.Text.Encoding.UTF8.GetBytes(xmlText)) Dim result As history = DirectCast(deserializer.Deserialize(stream), history) Return result End Using End Function |
C#
public class
history { public string location { get; set; } [XmlElement("era")] public List<era> era { get; set; } } public class era { [XmlElement("person")] public person[] person { get; set; } [XmlAttribute] public string name { get; set; } [XmlAttribute] public int start { get; set; } [XmlAttribute] public int end { get; set; } } public class person { public string image { get; set; } public string note { get; set; } [XmlAttribute] public string name { get; set; } } private string LoadXmlSample1Text() { StringBuilder xml = new StringBuilder(); xml.AppendLine("<?xml version=\"1.0\" encoding=\"utf-8\" ?>"); xml.AppendLine("<history>"); xml.AppendLine(" <location>日本</location>"); xml.AppendLine(" <era name=\"奈良時代\" start=\"710\" end=\"794\">"); xml.AppendLine(" <person name=\"坂上田村麻呂\">"); xml.AppendLine(" <image>https://xxxxxx/x1.jpg</image>"); xml.AppendLine(" <note>征夷大将軍</note>"); xml.AppendLine(" </person>"); xml.AppendLine(" </era>"); xml.AppendLine(" <era name=\"平安時代\" start=\"794\" end=\"1185\">"); xml.AppendLine(" <person name=\"藤原道長\">"); xml.AppendLine(" <note>摂政。藤原家の摂関政治の絶頂。</note>"); xml.AppendLine(" </person>"); xml.AppendLine(" <person name=\"清少納言\">"); xml.AppendLine(" <note>枕草子</note>"); xml.AppendLine(" </person>"); xml.AppendLine(" </era>"); xml.AppendLine("</history>"); return xml.ToString(); } private history TestXml() { string xmlText = this.LoadXmlSample1Text(); XmlSerializer deserializer = new XmlSerializer(typeof(history)); using(var stream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(xmlText))) { history result = deserializer.Deserialize(stream) as history; return result; } } |
この例では、マッピングした後、何もしていませんが、result変数の内容を見ると、ちゃんと値が入っているのわかります。
ここまでできれば後はプログラムで自由に利用できますね。
サンプル2のXMLではXML名前空間(xmlns)が使用されているため、マッピング先のクラスで属性としてXML名前空間を示す必要があります。
VB
<XmlRoot([Namespace]:="http://example.org")> Public Class parent <XmlElement([Namespace]:="http://www.w3.org/2000/svg")> Public Property svg As svg End Class Public Class svg <XmlAttribute> Public Property width As String <XmlAttribute> Public Property height As String <XmlAttribute> Public Property version As String <XmlElement([Namespace]:="http://www.w3.org/2000/svg")> Public Property ellipse As ellipse End Class Public Class ellipse <XmlAttribute> Public Property cx As String <XmlAttribute> Public Property cy As String <XmlAttribute> Public Property rx As String <XmlAttribute> Public Property ry As String End Class Private Function LoadXmlSample2Text() As String Dim xml As New System.Text.StringBuilder xml.AppendLine("<?xml version=""1.0"" standalone=""yes""?>") xml.AppendLine("<parent xmlns=""http://example.org""") xml.AppendLine(" xmlns:svg=""http://www.w3.org/2000/svg"">") xml.AppendLine(" <!-- parent contents here -->") xml.AppendLine(" <svg:svg width=""4cm"" height=""8cm"" version=""1.1"">") xml.AppendLine(" <svg:ellipse cx=""2cm"" cy=""4cm"" rx=""2cm"" ry=""1cm"" />") xml.AppendLine(" </svg:svg>") xml.AppendLine("</parent>") Return xml.ToString End Function Private Function TestXml() As parent Dim xmlText As String = Me.LoadXmlSample2Text Dim deserializer As New XmlSerializer(GetType(parent)) Using stream As New MemoryStream(System.Text.Encoding.UTF8.GetBytes(xmlText)) Dim result As parent= DirectCast(deserializer.Deserialize(stream), parent) Return result End Using End Function |
C#
[XmlRoot(Namespace="http://example.org")] public class parent { [XmlElement(Namespace="http://www.w3.org/2000/svg")] public svg svg { get; set; } } public class svg { [XmlAttribute] public string width { get; set; } [XmlAttribute] public string height { get; set; } [XmlAttribute] public string version { get; set; } [XmlElement(Namespace="http://www.w3.org/2000/svg")] public ellipse ellipse { get; set; } } public class ellipse { [XmlAttribute] public string cx { get; set; } [XmlAttribute] public string cy { get; set; } [XmlAttribute] public string rx { get; set; } [XmlAttribute] public string ry { get; set; } } private string LoadXmlSample2Text() { StringBuilder xml = new StringBuilder(); xml.AppendLine("<?xml version=\"1.0\" standalone=\"yes\"?>"); xml.AppendLine("<parent xmlns=\"http://example.org\""); xml.AppendLine(" xmlns:svg=\"http://www.w3.org/2000/svg\">"); xml.AppendLine(" <!-- parent contents here -->"); xml.AppendLine(" <svg:svg width=\"4cm\" height=\"8cm\" version=\"1.1\">"); xml.AppendLine(" <svg:ellipse cx=\"2cm\" cy=\"4cm\" rx=\"2cm\" ry=\"1cm\" />"); xml.AppendLine(" </svg:svg>"); xml.AppendLine("</parent>"); return xml.ToString(); } private parent TestXml() { string xmlText = this.LoadXmlSample2Text(); XmlSerializer deserializer = new XmlSerializer(typeof(parent)); using(var stream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(xmlText))) { parent result = deserializer.Deserialize(stream) as parent; return result; } } |
Visual Studioの機能で自動的にXMLをVB/C#のクラスに変換することができます。経験や知識が足りない場合はこの機能を活用しましょう。
それには、対象のXML全体をコピーしてから、 Visual Studioの編集メニューから[形式を選択して貼り付け] - [XMLをクラスとして貼り付ける]を選択します。
ただし、この変換は機械的なものであり、必要以上に複雑なプログラムが生成されることが多いようで、属性などをどのように書けばよいのかわからない場合の参考とする使い方が良さそうです。私はこの機能で生成されるクラスをそのまま使用したことは1度もありません。
自分で書く場合のコツは次の通りです。
XMLの定義がわかっているならば、XPathを使うことで簡単にXMLの値を取得することができます。クラスを定義しなくてもよいのでピンポイントで値をとってくれば良い場合は便利です。
たとえば、次のようにしてサンプル1の坂上田村麻呂の画像のUrlを取得できます。(XMLに即して言えば、name属性が"坂上田村麻呂"であるperson要素の子要素imageの値を取得できます。)
このプログラム中に登場する LoadXmlSample1Textメソッドは上述のプログラム例に登場するものと同じなので割愛しています。
VB
Dim xmlText
As String =
Me.LoadXmlSample1Text Dim document As New XmlDocument document.LoadXml(xmlText) Dim node As XmlNode = document.SelectSingleNode("//person[@name='坂上田村麻呂']/image") Debug.WriteLine(node.InnerText) |
C#
string xmlText =
this.LoadXmlSample1Text(); XmlDocument document = new XmlDocument(); document.LoadXml(xmlText); XmlNode node = document.SelectSingleNode("//person[@name='坂上田村麻呂']/image"); System.Diagnostics.Debug.WriteLine(node.InnerText); |
SelectSingleNodeメソッドの引数に設定しているの文字列がXPathです。これで取得する対象を指定します。
XPathの説明はこちらに記載されています。
https://docs.microsoft.com/ja-jp/previous-versions/dotnet/netframework-4.0/ms256086(v=vs.100)
SelectNodesメソッドを使うと、XPathに該当する複数の属性や要素を1度に取得することもできます。
VB
Dim xmlText
As String =
Me.LoadXmlSample1Text Dim document As New XmlDocument document.LoadXml(xmlText) Debug.WriteLine("■全personのname属性を列挙") Dim personNames As XmlNodeList = document.SelectNodes("//person/@name") For Each personName As XmlAttribute In personNames Debug.WriteLine("全人物:" & personName.Value) Next Debug.WriteLine("■平安時代のpersonのname属性とnote要素を列挙") Dim heianPersons As XmlNodeList = document.SelectNodes("//era[@name='平安時代']/person") For Each heianPerson As XmlElement In heianPersons Debug.WriteLine("平安時代の人物:" & heianPerson.GetAttribute("name")) Debug.WriteLine("ノート:" & heianPerson.SelectSingleNode("note").InnerText) Next |
C#
string xmlText =
this.LoadXmlSample1Text(); XmlDocument document = new XmlDocument(); document.LoadXml(xmlText); System.Diagnostics.Debug.WriteLine("■全personのname属性を列挙"); XmlNodeList personNames = document.SelectNodes("//person/@name"); foreach(XmlAttribute personName in personNames) { System.Diagnostics.Debug.WriteLine("全人物:" + personName.Value); } System.Diagnostics.Debug.WriteLine("■平安時代のpersonのname属性とnote要素を列挙"); XmlNodeList heianPersons = document.SelectNodes("//era[@name='平安時代']/person"); foreach(XmlElement heianPerson in heianPersons) { System.Diagnostics.Debug.WriteLine("平安時代の人物:" + heianPerson.GetAttribute("name")); System.Diagnostics.Debug.WriteLine("ノート:" + heianPerson.SelectSingleNode("note").InnerText); } |
XPathで "//person" と記述すると、そのXML内に存在するすべての person要素 を選択できるので、XMLの構造が完全にわかっていなくても、取得したいものが明確であれば使用できます。
XML名前空間が使われているXMLの場合は、XmlNamespaceManagerクラスを使用してプレフィックスと名前空間の関連付けを指定する必要があります。次に例を示します。
この例はサンプル2のXMLを前提に、svg:ellipse要素を取得します。
VB
Dim xmlText
As String =
Me.LoadXmlSample2Text Dim document As New XmlDocument document.LoadXml(xmlText) Dim nm As New XmlNamespaceManager(document.NameTable) nm.AddNamespace("svg", "http://www.w3.org/2000/svg") Dim node As XmlNode = document.SelectSingleNode("//svg:ellipse", nm) Debug.WriteLine(node.OuterXml) |
C#
string xmlText =
this.LoadXmlSample2Text(); XmlDocument document = new XmlDocument(); document.LoadXml(xmlText); XmlNamespaceManager nm = new XmlNamespaceManager(document.NameTable); nm.AddNamespace("svg", "http://www.w3.org/2000/svg"); XmlNode node = document.SelectSingleNode("//svg:ellipse", nm); System.Diagnostics.Debug.WriteLine(node.OuterXml); |
参考に、MicrosoftのドキュメントからXPath式の例を転載します。
元ドキュメントは https://docs.microsoft.com/ja-jp/previous-versions/dotnet/netframework-4.0/ms256086(v=vs.100) です。このドキュメントにはもっと多くの情報があります。
このドキュメントがアーカイブされた領域にあり、そのうち消えてしまいそうな気がするのでここに抜粋するものです。
XPath式 | 説明 |
---|---|
./author | 現在のコンテキスト内のすべての <author> 要素。 これは、次の行の式に等しくなることに注意してください。 |
author | 現在のコンテキスト内のすべての <author> 要素。 |
first.name | 現在のコンテキスト内のすべての <first.name> 要素。 |
/bookstore | このドキュメントのドキュメント要素 (<bookstore>)。 |
//author | このドキュメント内のすべての <author> 要素。 |
book[/bookstore/@specialty=@style] | ドキュメントのルートにある <bookstore> 要素の specialty 属性と同じ値の style 属性を持っているすべての <book> 要素。 |
author/first-name | <author> 要素の子要素であるすべての <first-name> 要素。 |
bookstore//title | <bookstore> 要素内の 1 段階以上深いレベル (任意の子孫) に含まれているすべての <title> 要素。 これは、次の行の式とは異なる点に注意してください。 |
bookstore/*/title | <bookstore> 要素の孫要素であるすべての <title> 要素。 |
bookstore//book/excerpt//emph | <bookstore> 要素内の任意の場所にある <book> 要素の子要素 <excerpt> 内の任意の場所にあるすべての <emph> 要素。 |
.//title | 現在のコンテキスト内の 1 段階以上深いレベルにあるすべての <title> 要素。 この状況は、ピリオド表記が必須である場合において、基本的に 1 回だけ発生することに注意してください。 |
author/* | <author> 要素の子要素であるすべての要素。 |
book/*/last-name | <book> 要素の孫要素であるすべての <last-name> 要素。 |
*/* | 現在のコンテキストのすべての孫要素です。 |
*[@specialty] | specialty 属性を持つすべての要素。 |
@style | 現在のコンテキストの style 属性。 |
price/@exchange | 現在のコンテキスト内の <price> 要素の exchange 属性。 |
price/@exchange/total | 属性には要素の子が含まれないため、空のノード セットが返ります。 この式は、XPath (XML Path Language) の文法上は使用可能ですが、厳密にいえば有効ではありません。 |
book[@style] | 現在のコンテキストの style 属性を持つすべての <book> 要素。 |
book/@style | 現在のコンテキストのすべての <book> 要素の style 属性。 |
@* | 現在の要素のコンテキストのすべての属性。 |
./first-name | 現在のコンテキスト ノード内のすべての <first-name> 要素。 これは、次の行の式に等しくなることに注意してください。 |
first-name | 現在のコンテキスト ノード内のすべての <first-name> 要素。 |
author[1] | 現在のコンテキスト ノード内の最初の <author> 要素。 |
author[first-name][3] | 子要素 <first-name> を持っている 3 番目の <author> 要素。 |
my:book | my 名前空間の <book> 要素。 |
my:* | my 名前空間のすべての要素。 |
@my:* | my 名前空間からのすべての要素 (これには、my 名前空間からの要素の修飾されていない属性は含まれません)。 |
XMLの定義があらかじめわかっていない場合、For Each(foreach)の列挙や、条件分岐、再帰などを使って構造を解析したり、値を検索、取得していくことになります。
方法は大きく分けて2つあります。
1つはXmlDocumentを使う方法です。XMLの内容をすべてメモリ上に展開してから処理するためプログラムはやりやすいです。コメントの検出もできます。
もう1つはXmlReaderを使う方法です。XMLを先頭から順次読み込みながら解析する方法で、プログラムの難易度は高いですが、きめ細かい処理が可能で、コメントや閉じタグの検出もできます。メモリを節約でき高速に動作します。
まずはXmlDocumentを使う例を示します。
上述のサンプル1・サンプル2のXMLでのみテストした簡易的な実装であり、対応できないケースもあるのではないかと思いますが、構造がわからないXMLに対するアプローチを示すのには十分だと思います。
VB
Private Sub TestXml() Dim xmlText As String = Me.LoadXmlSample1Text Dim document As New XmlDocument document.LoadXml(xmlText) Debug.WriteLine("要素 " & document.DocumentElement.Name) Debug.IndentSize = 2 Parse(document.DocumentElement) End Sub Private Sub Parse(node As XmlNode) Debug.IndentLevel += 1 For Each attr As XmlAttribute In node.Attributes Debug.WriteLine("属性 " & attr.Name & " = " & attr.Value) Next For Each childNode As XmlNode In node.ChildNodes Select Case childNode.NodeType Case XmlNodeType.Element Debug.WriteLine("要素 " & childNode.Name) Parse(childNode) Case XmlNodeType.Text Dim value As String = childNode.Value If String.IsNullOrWhiteSpace(value) Then 'このサンプルでは空白または改行は無視します。 Else Debug.WriteLine(value) End If Case Else Debug.Write(childNode.NodeType.ToString & " ") Debug.WriteLine(childNode.OuterXml) End Select Next Debug.IndentLevel -= 1 End Sub |
C#
private void TestXml() { string xmlText = this.LoadXmlSample1Text(); XmlDocument document = new XmlDocument(); document.LoadXml(xmlText); System.Diagnostics.Debug.WriteLine("要素 " + document.DocumentElement.Name); System.Diagnostics.Debug.IndentSize = 2; Parse(document.DocumentElement); } private void Parse(XmlNode node) { System.Diagnostics.Debug.IndentLevel += 1; foreach (XmlAttribute attr in node.Attributes) { System.Diagnostics.Debug.WriteLine("属性 " + attr.Name + " = " + attr.Value); } foreach (XmlNode childNode in node.ChildNodes) { switch (childNode.NodeType) { case XmlNodeType.Element: System.Diagnostics.Debug.WriteLine("要素 " + childNode.Name); Parse(childNode); break; case XmlNodeType.Text: string value = childNode.Value; if (string.IsNullOrWhiteSpace(value)) { //このサンプルでは空白または改行は無視します。 } else { System.Diagnostics.Debug.WriteLine(value); } break; default: System.Diagnostics.Debug.Write(childNode.NodeType.ToString() + " "); System.Diagnostics.Debug.WriteLine(childNode.OuterXml); break; } //switch } //foreach System.Diagnostics.Debug.IndentLevel -= 1; } //Parse |
このプログラムを実行すると出力ウィンドウには次のように出力されます。
要素 history 要素 location 日本 要素 era 属性 name = 奈良時代 属性 start = 710 属性 end = 794 要素 person 属性 name = 坂上田村麻呂 要素 image https://xxxxxx/x1.jpg 要素 note 征夷大将軍 要素 era 属性 name = 平安時代 属性 start = 794 属性 end = 1185 要素 person 属性 name = 藤原道長 要素 note 摂政。藤原家の摂関政治の絶頂。 要素 person 属性 name = 清少納言 要素 note 枕草子 |
次にXmlReaderを使う例を示します。
サンプル1のXMLでは結果は上記のXmlDocumentの例と同じになります。サンプル2を対象にするとコメントの出力に少し違いがあることがわかります。
VB
Dim xmlText
As String =
Me.LoadXmlSample1Text Dim settings As New XmlReaderSettings() Debug.IndentSize = 2 Debug.IndentLevel = 0 Using stream As New MemoryStream(System.Text.Encoding.UTF8.GetBytes(xmlText)) Using reader As XmlReader = XmlReader.Create(stream, settings) Do While reader.Read() Select Case (reader.NodeType) Case XmlNodeType.Element Debug.WriteLine("要素 " & reader.Name) Debug.IndentLevel += 1 If reader.HasAttributes Then Do While reader.MoveToNextAttribute Debug.WriteLine("属性 " & reader.Name & " = " & reader.Value) Loop reader.MoveToElement() End If Case XmlNodeType.Text Dim value As String = reader.Value If String.IsNullOrWhiteSpace(value) Then 'このサンプルでは空白または改行は無視します。 Else Debug.WriteLine(value) End If Case XmlNodeType.EndElement '要素の終了(閉じタグなど) Debug.IndentLevel -= 1 Case XmlNodeType.Comment Debug.WriteLine("Comment " & reader.Value) End Select Loop End Using End Using |
C#
string xmlText =
this.LoadXmlSample1Text(); XmlReaderSettings settings = new XmlReaderSettings(); System.Diagnostics.Debug.IndentSize = 2; System.Diagnostics.Debug.IndentLevel = 0; using (var stream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(xmlText))) { using (var reader = XmlReader.Create(stream, settings)) { while (reader.Read()) { switch (reader.NodeType) { case XmlNodeType.Element: System.Diagnostics.Debug.WriteLine("要素 " + reader.Name); System.Diagnostics.Debug.IndentLevel += 1; if (reader.HasAttributes) { while (reader.MoveToNextAttribute()) { System.Diagnostics.Debug.WriteLine("属性 " + reader.Name + " = " + reader.Value); } reader.MoveToElement(); } break; case XmlNodeType.Text: string value = reader.Value; if (string.IsNullOrWhiteSpace(value)) { //このサンプルでは空白または改行は無視します。 } else { System.Diagnostics.Debug.WriteLine(value); } break; case XmlNodeType.EndElement: //要素の終了(閉じタグなど) System.Diagnostics.Debug.IndentLevel -= 1; break; case XmlNodeType.Comment: System.Diagnostics.Debug.WriteLine("Comment " + reader.Value); break; } //switch } //while } //using } //using |