C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[11]: InnerTextによるXMLノードの取得


(過去ログ 96 を表示中)

[トピック内 13 記事 (1 - 13 表示)]  << 0 >>

■57446 / inTopicNo.1)  InnerTextによるXMLノードの取得
  
□投稿者/ 上条 (1回)-(2011/02/27(Sun) 20:16:56)

分類:[C#] 

あるXMLのノード間にあるテキストを取得するため.InnerTextを使いました。
しかし、改行コードを含んだテキストを.InnerTextを用いて取得しようとすると
テキストの取得が出来ず応答が停止してしまいます。
この場合ノード間にあるテキストを改行したままの状態で取得するのは.InnerTextでは無理なのでしょうか?

---------------------------------XMLの一部
<chat thread="1074179716" no="1" vpos="7702">これは通常のテキストです</chat>
↑この場合は.InnerTextで正常に取得出来ます。

↓こうなると取得出来なくなります。
<chat thread="1074179716" no="2" vpos="29852">このテキストは
改行文字を含んでいるようです</chat>

---------------------------------ソースの一部
                    xml = xml.Replace('\0', '\n');              
                    string[] lines = xml.Split('\n');
                    foreach (string line in lines)
                    {
                        if (line.StartsWith("<chat") && line.EndsWith("</chat>"))
                        {
                        string come = "";
                        xdoc = new XmlDocument();
                        xdoc.PreserveWhitespace = true;
                        xdoc.LoadXml(line);
                        come = xdoc.InnerText;
            this.dataGridView1.Rows.Add(come);
                        }
                    }

開発環境:VS2010 Express C#

引用返信 編集キー/
■57447 / inTopicNo.2)  Re[1]: InnerTextによるXMLノードの取得
□投稿者/ shu (478回)-(2011/02/27(Sun) 20:55:40)
No57446 (上条 さん) に返信

string[] lines = xml.Split('\n');
により改行で分割しているので

<chat thread="1074179716" no="2" vpos="29852">このテキストは



改行文字を含んでいるようです</chat>

は別に処理されますね。
引用返信 編集キー/
■57449 / inTopicNo.3)  Re[1]: InnerTextによるXMLノードの取得
□投稿者/ 魔界の仮面弁士 (2114回)-(2011/02/27(Sun) 21:12:38)
No57446 (上条 さん) に返信
> テキストの取得が出来ず応答が停止してしまいます。
ちょっと状況が見えてこないので、少し確認させてください。

「応答が停止」というのは、以下のいずれの状態でしょうか?

(1) 特定の例外が発生する。
→どの行でエラーになっているのか? また、その例外はどのようなものか?
 (XmlException、ArgumentNullException、NullReferenceException など)

(2) アプリケーションが「応答なし」の状態に陥る。
→どの行までは実行できていて、どの行が実行されたときに停止するのか?
 また、停止した時、各変数の値はどうなっているのか?

(3) エラーは発生しないが、テキストの取得が行われない。
→ステップ実行で、そのコードが実行されていることを確認してあるか?



> .InnerTextでは無理なのでしょうか?
たとえば、元の xml データが
    string xml;
    xml = "<chat thread=\"1074179716\" no=\"2\" vpos=\"29852\">このテキストは";
    xml += "\r\n改行文字を含んでいるようです</chat>";
であったとしましょう。

これを
    XmlDocument sample = new XmlDocument();
    sample.LoadXml(xml);
    MessageBox.Show(sample.InnerText);
として実行しても、特に問題無く取り出せますから、InnerText 自体には
改行の有無は関係ないハズです。それが \r だろうと \r\n だろうと \n だろうと。


ただし提示されたコードでは、改行単位での Split を行っている点が気になります。
(何故、そのような処理が必要なのでしょうか?)

上記の xml 変数を Split した場合、
> xml = xml.Replace('\0', '\n');
> string[] lines = xml.Split('\n');
の処理結果は、
   lines[0] は『<chat thread="1074179716" no="2" vpos="29852">このテキストは\r』
   lines[1] は『改行文字を含んでいるようです</chat>』
のように分解されることになりますね。ということは、

>  foreach (string line in lines)
>  {
>      if (line.StartsWith("<chat") && line.EndsWith("</chat>"))
>      {
の if 文には、そもそも絶対に入ってこないことになりますが……その点は大丈夫でしょうか?

また、取得したデータの前後に空白やタブが含まれていた場合、たとえば
   line ="  <chat thread=…";
な状況においては、line.StartsWith("<chat") は false になりますので、
やはり、if の部分の処理は実行されません。こちらも注意が必要です。


もし、そうした余計な文字が無く、かつ、元データの改行コードが \r だけだった場合には、lines 配列は
   lines[0] は『<chat thread="1074179716" no="2" vpos="29852">このテキストは\r改行文字を含んでいるようです</chat>』
の一つだけになりますので、if 内にて正しく処理され、期待通りに this.dataGridView1.Rows.Add(come); されるはずです。

それとも、dataGridView1.Rows.Add はされているのに、それが表示されないという状況なのでしょうか?

引用返信 編集キー/
■57450 / inTopicNo.4)  Re[2]: InnerTextによるXMLノードの取得
□投稿者/ 上条 (2回)-(2011/02/27(Sun) 22:35:59)
> 「応答が停止」というのは、以下のいずれの状態でしょうか?
> 
> (3) エラーは発生しないが、テキストの取得が行われない。
> →ステップ実行で、そのコードが実行されていることを確認してあるか?

説明不足でした。
現在の状況は(3)の状態です。
ステップインでエラーが発生しなかったので
ご指摘のとおりのSplitの部分がおかしい事に気付きました。

>改行単位での Split を行っている点
XMLのノードの並びが1行ずつだったのでつい...。

となると、今回の場合1行単位ではなく<chat></chat>単位で区切ることになるのですが
どうやって分けたら良いでしょうか?(,はありませんし...)

ちなみにこんなXMLです
----------------------------------
<thread resultcode="0" thread="1074256157" />
<chat thread="1074256157" no="1" vpos="4370">1番目</chat>
<chat thread="1074256157" no="2" vpos="6917">2番目</chat>
<chat thread="1074256157" no="3" vpos="26877">3番目</chat>
<chat thread="1074256157" no="4" vpos="30771">4番目</chat>
...

引用返信 編集キー/
■57451 / inTopicNo.5)  Re[3]: InnerTextによるXMLノードの取得
□投稿者/ shu (479回)-(2011/02/27(Sun) 23:36:01)
2011/02/27(Sun) 23:46:09 編集(投稿者)
No57450 (上条 さん) に返信

各行に分解しないで、こんな感じでどう?

            var Src = "<thread resultcode=\"0\" thread=\"1074256157\" />\n" +
                    "<chat thread=\"1074256157\" no=\"1\" vpos=\"4370\">1番目</chat>\n" +
                    "<chat thread=\"1074256157\" no=\"2\" vpos=\"6917\">2番目</chat>\n" +
                    "<chat thread=\"074256157\" no=\"3\" vpos=\"26877\">3番目</chat>\n" +
                    "<chat thread=\"074256157\" no=\"4\" vpos=\"30771\">4番目</chat>";

            var xdoc = new XmlDocument();
            //--- Rootは一つの為<roor></root>でくくる
            xdoc.LoadXml(String.Format("<root>{0}</root>", Src));
            foreach (XmlNode ndTmp in xdoc.ChildNodes)
            {
                foreach (XmlNode nd in ndTmp.ChildNodes)
                {
                    var attr = nd.Attributes;
                    if (nd.Name == "chat")
                    {
                        Console.WriteLine(String.Format("{0}:{1}:{2}", nd.Name, attr["thread"].Value, nd.InnerText));
                    }
                }
            }

引用返信 編集キー/
■57452 / inTopicNo.6)  Re[4]: InnerTextによるXMLノードの取得
□投稿者/ 上条 (3回)-(2011/02/28(Mon) 02:02:36)
2011/02/28(Mon) 02:32:09 編集(投稿者)
2011/02/28(Mon) 02:32:00 編集(投稿者)
2011/02/28(Mon) 02:31:53 編集(投稿者)
<pre><pre>■No57451 (shu さん) に返信
> 2011/02/27(Sun) 23:46:09 編集(投稿者)
> 
> ■No57450 (上条 さん) に返信
> 
> 各行に分解しないで、こんな感じでどう?
> 
>             var Src = "<thread resultcode=\"0\" thread=\"1074256157\" />\n" +
>                     "<chat thread=\"1074256157\" no=\"1\" vpos=\"4370\">1番目</chat>\n" +
>                     "<chat thread=\"1074256157\" no=\"2\" vpos=\"6917\">2番目</chat>\n" +
>                     "<chat thread=\"074256157\" no=\"3\" vpos=\"26877\">3番目</chat>\n" +
>                     "<chat thread=\"074256157\" no=\"4\" vpos=\"30771\">4番目</chat>";
> 
>             var xdoc = new XmlDocument();
>             //--- Rootは一つの為<roor></root>でくくる
>             xdoc.LoadXml(String.Format("<root>{0}</root>", Src));
>             foreach (XmlNode ndTmp in xdoc.ChildNodes)
>             {
>                 foreach (XmlNode nd in ndTmp.ChildNodes)
>                 {
>                     var attr = nd.Attributes;
>                     if (nd.Name == "chat")
>                     {
>                         Console.WriteLine(String.Format("{0}:{1}:{2}", nd.Name, attr["thread"].Value, nd.InnerText));
>                     }
>                 }
>             }


やってみましたが改行コードを含むテキストの取得はしませんでした。
やはりSplitで1行だけ取得するのが問題ですね。
※補足:このXMLはサーバーからリアルタイムに送られてくる物です。




現在は以下のような状況

<thread resultcode="0" thread="1074256157" />
<chat thread="1074256157" no="1" vpos="4370">1番目です</chat>
<chat thread="1074256157" no="2" vpos="6917">2番目です</chat>
<chat thread="1074256157" no="3" vpos="26877">3番目です</chat>
<chat thread="1074256157" no="4" vpos="30771">4番目
です</chat>
<chat thread="1074256157" no="5" vpos="30771">5番目です</chat>

Datagridviewでは

1番目です
2番目です
3番目です


と表示されます</pre></pre>

引用返信 編集キー/
■57453 / inTopicNo.7)  Re[5]: InnerTextによるXMLノードの取得
□投稿者/ shu (480回)-(2011/02/28(Mon) 07:53:05)
2011/02/28(Mon) 08:07:24 編集(投稿者)

No57452 (上条 さん) に返信

> やってみましたが改行コードを含むテキストの取得はしませんでした。
> やはりSplitで1行だけ取得するのが問題ですね。
> ※補足:このXMLはサーバーからリアルタイムに送られてくる物です。

私の提示したのはSplitを使っていませんよ。送られてきたXMLをSplitしないで
Srcの代わりに処理するようにしてみて下さい。XMLがタグの区切りで終わっていれば
何行あっても同時に処理出来るかと思います。
引用返信 編集キー/
■57468 / inTopicNo.8)  Re[6]: InnerTextによるXMLノードの取得
□投稿者/ 上条 (4回)-(2011/02/28(Mon) 18:36:03)
> 私の提示したのはSplitを使っていませんよ。送られてきたXMLをSplitしないで
> Srcの代わりに処理するようにしてみて下さい。XMLがタグの区切りで終わっていれば
> 何行あっても同時に処理出来るかと思います。

やってみましたが何も表示されなかったため
xml = xml.Replace('\0', '\n');の後にshuさんのコードを記述しました。
すると途中まで同じテキストを表示し
改行コードを含んだテキストは表示されずに処理が続行されました。

------------------------------------------
Datagridviewで以下のような表示になる

1番目
1番目
1番目
1番目
1番目
1番目
7番目
8番目
10番目(改行コードを含む9番目は表示されず10番目からの表示となる)

------------------------------------ソース
while (true)
            {
                byte[] resBytes = new byte[MAX_RECEIVE_SIZE];
                int resSize = sock.Receive(resBytes, resBytes.Length, System.Net.Sockets.SocketFlags.None);

                if (resSize == 0)
                {
                    return;
                }
                xml = prev + Encoding.UTF8.GetString(resBytes, 0, resSize);
                
                xml = xml.Replace('\0', '\n');←これが無いと何も表示されない
                string come2 = "";
                var xdoc1 = new XmlDocument();
                xdoc1.LoadXml(String.Format("<root>{0}</root>", xml));
           
                foreach (XmlNode ndtmp in xdoc1.ChildNodes)
                {
                    foreach (XmlNode nd in ndtmp.ChildNodes)
                    {
                        var attr = nd.Attributes;
                        if (nd.Name == "chat")
                        {
                            come2 = String.Format(nd.InnerText);
                        }
                    }
                }
                this.dataGridView1.Rows.Add(come2);
                //これより下にbreak;はありますが省略しています
            }

引用返信 編集キー/
■57472 / inTopicNo.9)  Re[7]: InnerTextによるXMLノードの取得
□投稿者/ shu (485回)-(2011/02/28(Mon) 22:23:29)
2011/02/28(Mon) 22:36:22 編集(投稿者)

No57468 (上条 さん) に返信

> xml = xml.Replace('\0', '\n');←これが無いと何も表示されない
> string come2 = "";
この間にxmlが</chat>を含んでいるかチェックして含んでいなければcontinueして含んでいたら一番後ろの</chat>までで分断するとよいかもしれません。


> if (nd.Name == "chat")
> {
> come2 = String.Format(nd.InnerText);
※1
> }

> }
> }

> this.dataGridView1.Rows.Add(come2);
これを※1へ移動
これでだいぶ変わるかと思います。
prevに関する処理はうまく行われていると仮定します。


引用返信 編集キー/
■57473 / inTopicNo.10)  Re[8]: InnerTextによるXMLノードの取得
□投稿者/ らら (1回)-(2011/02/28(Mon) 22:41:35)
ニコニコ生放送のコメント取得のようにお見受けしました。

リアルタイムで送られてくるわけでパケットをサイズによって次回受信になってる場合があるため
全体のソースを見てないのでいえないですが、xmlとして完結指定ない部分が含まれてないですか?


引用返信 編集キー/
■57477 / inTopicNo.11)  Re[9]: InnerTextによるXMLノードの取得
□投稿者/ 上条 (5回)-(2011/03/01(Tue) 05:34:24)
□投稿者/ shu さんへ


前回のヒントで改行コードを含んだテキストをノード間より取得できるようになりました。
ありがとうございます。
ただ問題としてchatの属性値であるnoの値が取得出来なくなりました。
現状を維持したままchatの属性値であるnoの値を取得できませんでしょうか。
質問ばかりで申し訳ありません。

----------------------成功コード
        string come2 = "";
                var xdoc1 = new XmlDocument();
                xdoc1.LoadXml(String.Format("<root>{0}</root>", xml));
                foreach (XmlNode ndtmp in xdoc1.ChildNodes)
                {
                    foreach (XmlNode nd in ndtmp.ChildNodes)
                    {
                        var attr = nd.Attributes;
                        if (nd.Name == "chat")
                        {
                            come2 = String.Format(nd.InnerText);
                        
                            this.Invoke(new MethodInvoker(delegate
                            {
                                this.dataGridView1.Rows.Add(comecount, come2);
                            }));
                        }
                    }
                }

--------------------------noの値は表示されるがテキストが全て同じになるコード
        string comecount = "";
                XmlNodeList node = root.GetElementsByTagName("chat");
                XmlElement xmlname = (XmlElement)node.Item(0);
                comecount = xmlname.GetAttribute("no");

                string come2 = "";
                var xdoc1 = new XmlDocument();
                xdoc1.LoadXml(String.Format("<root>{0}</root>", xml));
                foreach (XmlNode ndtmp in xdoc1.ChildNodes)
                {
                    foreach (XmlNode nd in ndtmp.ChildNodes)
                    {
                        var attr = nd.Attributes;
                        MessageBox.Show(nd.InnerText);
                        if (nd.Name == "chat")
                        {
                            come2 = String.Format(nd.InnerText);
                        
                            this.Invoke(new MethodInvoker(delegate
                            {
                                this.dataGridView1.Rows.Add(comecount, come2);
                            }));
                        }
                    }
                }
--------------------------------------------
□投稿者/ らら さんへ

はい、確かにニコニコ生放送関係です。
>xmlとして完結指定ない部分が含まれてないですか?
つまり完成したXMLを読み込んでいるわけではないということでしょうか?

引用返信 編集キー/
■57478 / inTopicNo.12)  Re[10]: InnerTextによるXMLノードの取得
□投稿者/ shu (487回)-(2011/03/01(Tue) 07:50:27)
2011/03/01(Tue) 08:02:18 編集(投稿者)

No57477 (上条 さん) に返信

> come2 = String.Format(nd.InnerText);
このタイミングで
attr["no"].Valueでnoが取得出来るかと思いますが、どうでしょう?
引用返信 編集キー/
■57482 / inTopicNo.13)  Re[11]: InnerTextによるXMLノードの取得
□投稿者/ 上条 (6回)-(2011/03/01(Tue) 10:35:23)
2011/03/01(Tue) 10:41:34 編集(投稿者)

No57478 (shu さん) に返信
>
>>come2 = String.Format(nd.InnerText);
> このタイミングで
> attr["no"].Valueでnoが取得出来るかと思いますが、どうでしょう?

ありがとうございます、無事改行コードを含んだテキストの表示と
chatの属性値noの値が取得できるようになりました。
shuさん、ららさん、魔界の仮面弁士さんありがとうございました。
本当に助かりました。

後は出来るだけ頑張って完成させようと思います。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -