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

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

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

Re[7]: C# XMLファイル形式の指定要素の属性値取得


(過去ログ 76 を表示中)

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

■44415 / inTopicNo.1)  C# XMLファイル形式の指定要素の属性値取得
  
□投稿者/ Bianchi (1回)-(2009/12/08(Tue) 23:28:48)

分類:[C#] 

開発環境:Visual Studio 2008
使用言語:C#
------------------------------------------------------------------------------------------
XMLファイル形式で記述されているファイルの指定要素から属性値を取り出したいです。
※GPSデータです。

下記ファイルの中身にあるとおり
<Trackpoint>
<Time>2009-10-10T23:28:09Z</Time>
<Position>
<LatitudeDegrees>34.8101051</LatitudeDegrees>
<LongitudeDegrees>135.3483362</LongitudeDegrees>
</Position>
<AltitudeMeters>64.0650635</AltitudeMeters>
<DistanceMeters>0.0000000</DistanceMeters>
<HeartRateBpm xsi:type="HeartRateInBeatsPerMinute_t">
<Value>66</Value>
</HeartRateBpm>
<SensorState>Absent</SensorState>
<Extensions>
<TPX xmlns="http://www.garmin.com/xmlschemas/ActivityExtension/v2" CadenceSensor="Bike"/>
</Extensions>
</Trackpoint>
という、連続したデータが不特定秒毎にあります。
このデータから<Time><LatitudeDegrees><LongitudeDegrees><AltitudeMeters><DistanceMeters><Value>の要素と取り込み
String[][] strに対して
str[0][0]・・・timeデータ
str[0][1]・・・LatitudeDegreesデータ
str[・・・
とValueデータまで取り込み、
次のTime分を
str[1][0]・・・timeデータ(先程のデータの次)
str[1][1]・・・LatitudeDegreesデータ
といった具合に格納。

ただし、timeデータは確実にあるのですが、LatitudeDegreeやその他のデータが空であったり、その要素すらない場合
がございます。
<Trackpoint>
<Time>2009-10-10T23:28:08Z</Time>
</Trackpoint>
のように。

なんとかXMLのデータとして読込みたいので、お力をお貸し願います。
要素があったりなかったりというのに、うまく対応できません。

--XMLファイルの中身-----------------------------------------------------------------------
<Activities>
<Activity Sport="Biking">
<Id>2009-10-10T23:28:05Z</Id>
<Lap StartTime="2009-10-10T23:28:05Z">
<TotalTimeSeconds>567.5500000</TotalTimeSeconds>
<DistanceMeters>2138.0234375</DistanceMeters>
<MaximumSpeed>12.3328228</MaximumSpeed>
<Calories>185</Calories>
<AverageHeartRateBpm xsi:type="HeartRateInBeatsPerMinute_t">
<Value>127</Value>
</AverageHeartRateBpm>
<MaximumHeartRateBpm xsi:type="HeartRateInBeatsPerMinute_t">
<Value>140</Value>
</MaximumHeartRateBpm>
<Intensity>Active</Intensity>
<TriggerMethod>Manual</TriggerMethod>
<Track>
<Trackpoint>
<Time>2009-10-10T23:28:08Z</Time>
</Trackpoint>
<Trackpoint>
<Time>2009-10-10T23:28:09Z</Time>
<Position>
<LatitudeDegrees>34.8101051</LatitudeDegrees>
<LongitudeDegrees>135.3483362</LongitudeDegrees>
</Position>
<AltitudeMeters>64.0650635</AltitudeMeters>
<DistanceMeters>0.0000000</DistanceMeters>
<HeartRateBpm xsi:type="HeartRateInBeatsPerMinute_t">
<Value>66</Value>
</HeartRateBpm>
<SensorState>Absent</SensorState>
<Extensions>
<TPX xmlns="http://www.garmin.com/xmlschemas/ActivityExtension/v2" CadenceSensor="Bike"/>
</Extensions>
</Trackpoint>
<Trackpoint>
<Time>2009-10-10T23:28:10Z</Time>
<Position>
<LatitudeDegrees>34.8101310</LatitudeDegrees>
<LongitudeDegrees>135.3483426</LongitudeDegrees>
</Position>
<AltitudeMeters>65.5070801</AltitudeMeters>
<DistanceMeters>3.4017792</DistanceMeters>
<HeartRateBpm xsi:type="HeartRateInBeatsPerMinute_t">
<Value>67</Value>
</HeartRateBpm>
<SensorState>Absent</SensorState>
<Extensions>
<TPX xmlns="http://www.garmin.com/xmlschemas/ActivityExtension/v2" CadenceSensor="Bike"/>
</Extensions>
</Trackpoint>
<Trackpoint>
<Time>2009-10-10T23:28:15Z</Time>
<Position>
<LatitudeDegrees>34.8103160</LatitudeDegrees>
<LongitudeDegrees>135.3483677</LongitudeDegrees>
</Position>
<AltitudeMeters>63.1036377</AltitudeMeters>
<DistanceMeters>23.7893047</DistanceMeters>
<HeartRateBpm xsi:type="HeartRateInBeatsPerMinute_t">
<Value>73</Value>
</HeartRateBpm>
<SensorState>Absent</SensorState>
<Extensions>
<TPX xmlns="http://www.garmin.com/xmlschemas/ActivityExtension/v2" CadenceSensor="Bike"/>
</Extensions>
</Trackpoint>
     ・・・・・
-------------------------------------------------------------------------------------------------------
引用返信 編集キー/
■44416 / inTopicNo.2)  Re[1]: C# XMLファイル形式の指定要素の属性値取得
□投稿者/ επιστημη (2307回)-(2009/12/08(Tue) 23:36:49)
επιστημη さんの Web サイト
> なんとかXMLのデータとして読込みたいので、お力をお貸し願います。
> 要素があったりなかったりというのに、うまく対応できません。

コード見せてください。

引用返信 編集キー/
■44419 / inTopicNo.3)  Re[2]: C# XMLファイル形式の指定要素の属性値取得
□投稿者/ Bianchi (3回)-(2009/12/09(Wed) 00:14:09)
No44416 (επιστημη さん) に返信
>>なんとかXMLのデータとして読込みたいので、お力をお貸し願います。
>>要素があったりなかったりというのに、うまく対応できません。
>
> コード見せてください。
>
-------------------------------------------------------------------------------------

private const string nodeText =
"[name()='Time' or name()='LatitudeDegrees' " +
"or name()='LongitudeDegrees' or name()='AltitudeMeters '" +
"or name()='DistanceMeters' or name()='Value']";
private XmlDocument doc;


private void GetData() {

DialogResult ret = this.ofd.ShowDialog();
List<string> list = new List<string>();

if (ret == DialogResult.OK) {

doc = new XmlDocument();
doc.PreserveWhitespace = false;
doc.Load(ofd.FileName);
foreach ( XmlNode node in doc.SelectNodes( "//*" + nodeText + "/text()|//@*" + nodeText ) ) {
list.Add( node.Value );
}
// Listの中に一旦格納した後、str[][] に順番に入れる<省略>

} else {

}
}

    これで、指定要素の属性は取得できるのですが、抜けがあったりしても関係なく順番に Listに格納されて
    しまうので、あとでstr[][]へ格納できない状態です。
引用返信 編集キー/
■44421 / inTopicNo.4)  Re[3]: C# XMLファイル形式の指定要素の属性値取得
□投稿者/ 渋木宏明(ひどり) (1258回)-(2009/12/09(Wed) 01:37:23)
渋木宏明(ひどり) さんの Web サイト
値と、値が存在する/しないを表現したいなら、Nullable 使えばいいのでは。

引用返信 編集キー/
■44424 / inTopicNo.5)  Re[4]: C# XMLファイル形式の指定要素の属性値取得
□投稿者/ なちゃ (340回)-(2009/12/09(Wed) 08:45:58)
スキーマは公開されてないですか?
# xsdファイルとか

xsdがあるならxsd.exeとか使った方が楽な気が。

引用返信 編集キー/
■44470 / inTopicNo.6)  Re[5]: C# XMLファイル形式の指定要素の属性値取得
□投稿者/ Bianchi (5回)-(2009/12/09(Wed) 22:03:04)
No44424 (なちゃ さん) に返信
> スキーマは公開されてないですか?
> # xsdファイルとか
>
> xsdがあるならxsd.exeとか使った方が楽な気が。
>
すいません。いまXML Schemaでググったりしてみましたが、よく理解できてません。

もし宜しければ、どこかのHPをご紹介いただけないでしょうか。勉強します。
引用返信 編集キー/
■44472 / inTopicNo.7)  Re[4]: C# XMLファイル形式の指定要素の属性値取得
□投稿者/ Bianchi (6回)-(2009/12/09(Wed) 22:15:54)
No44421 (渋木宏明(ひどり) さん) に返信
> 値と、値が存在する/しないを表現したいなら、Nullable 使えばいいのでは。
>

Nullableの使い方をネットで調べましたが、Nullの場合は代用値を入れる 等の処理ができるようで、
使っていけそうですが、要素(ルート)自体がない場合には適用できなさそうですが、どうなんでしょうか?

で、今の自分で出来る方法として、あまり良い内容ではないのですが、
一旦、xmlnodeに取り込んで、それをDataTableに入れ直すという方法です。

<Time>タグは必ずありますので、それをキーにしてデータを整理する といった方法で格納しました。

---コード-----------------------------------------------------------------------------
private const string nodeText =
"[name()='Time' or name()='LatitudeDegrees' " +
"or name()='LongitudeDegrees' or name()='AltitudeMeters '" +
"or name()='DistanceMeters' or name()='Value']";
private XmlDocument doc;

public DataTable GetData() {

DialogResult ret = this.ofd.ShowDialog();
List<string> list = new List<string>();
List<string> time = new List<string>();

if ( ret == DialogResult.OK ) {

doc = new XmlDocument();
doc.PreserveWhitespace = false;
doc.Load( ofd.FileName );

foreach ( XmlNode node in doc.SelectNodes( "//*[name()='Time']/text()|//@*[name()='Time']" ) ) {
time.Add( node.Value );
}

foreach ( XmlNode node in doc.SelectNodes( "//*" + nodeText + "/text()|//@*" + nodeText ) ) {
list.Add( node.Value );
}
}

return GetTable( time.Count, list );
}

private DataTable GetTable( int number, List<string> data ) {

DataTable dt = new DataTable( "GPS" );
// Time, LatitudeDegrees, LongitudeDegrees, AltitudeMeters, DistanceMeters, Valueを格納
dt.Columns.Add( "Time", typeof( String ) );
dt.Columns.Add( "LatitudeDegrees", typeof( Double ) );
dt.Columns.Add( "LongitudeDegrees", typeof( Double ) );
dt.Columns.Add( "AltitudeMeters", typeof( Double ) );
dt.Columns.Add( "DistanceMeters", typeof( Double ) );
dt.Columns.Add( "Value", typeof( Double ) );

int inumber = 0;

for ( int i = 0; i < data.Count; i++ ) {
if ( "Z" == data[ i ].Substring( data[ i ].Length - 1 ) ) {
var row = dt.NewRow();
if ( i + dt.Rows.Count >= data.Count ) break;

row[0] = data[ i ];

i++;
for ( int j = 1; j < dt.Columns.Count; j++ ) {
if ( "Z" != data[ i ].Substring( data[ i ].Length - 1 ) ) {
row[ j ] = data[ i ];
} else {
row[ j ] = "0";
}
i++;
}
dt.Rows.Add( row );
inumber++;
}
}

return dt;

}
-------------こちらは2次元配列に格納する場合---------------------------------------------

//List<string>データをString[]に格納してList<String[]>に置き換える
//はずが、どうもList list.Add(**)とするも後ろに追加ではなく、
//すべて書き換えになるので、しょうがないので2次元配列で対処
//DataTableに入れた方がいいかな。
private String[,] Change( int number, List<string> data ) {

// Time, LatitudeDegrees, LongitudeDegrees, AltitudeMeters, DistanceMeters, Valueを格納
int value = 6;
string[] str = new string[ value ];

List<String[]> list = new List<string[]>();
String[ , ] strArray = new String[ number, value ];

int inumber = 0;

for ( int i = 0; i < data.Count; i++ ) {
if ( "Z" == data[ i ].Substring( data[ i ].Length - 1 ) ) {
if ( i + value >= data.Count ) break;

strArray[ inumber, 0 ] = data[ i ];

i++;
for ( int j = 1; j < value; j++ ) {
if ( "Z" != data[ i ].Substring( data[ i ].Length - 1 ) ) {
strArray[ inumber, j ] = data[ i ];
} else {
strArray[ inumber, j ] = "0";
}
i++;
}
inumber++;
}
}
return strArray;
}
---------------------------------------------------------------------------------------
次にList<String[]>に格納しようとしたのですが、バグなのでしょうか
List.Add(**)としてループでどんどん追加したのですが、なぜか格納されたすべてのデータが、
最後に格納したデータに書き換えられてしまいます。

例えば、
list.Add("1");
list.Add("2");
list.Add("3");
の中身は、
1
2
3
となると思うのですが、これが
3
3
3
となってしまうのです。それがずーっと解決できなかったもので、2次配列やDataTableに格納となった次第です。
ちなみにこちらがそのコードです。何がおかしいのでしょうか?

// IEnumerator<string> ie = motoData.GetEnumerator();

// while ( ie.MoveNext() ) {

// if ( "Z" == ie.Current.Substring( ie.Current.Length - 1 ) ) {
// //Time情報から格納開始し、Valueデータ数あればそのまま格納
// //無ければ"0"で補完でしょうがないや。
// str[ 0 ] = ie.Current;
// ie.MoveNext();

// for ( int i = 1; i < value; i++ ) {
// if ( "Z" != ie.Current.Substring( ie.Current.Length - 1 ) ) {
// str[ i ] = ie.Current;
// ie.MoveNext();
// } else {
// for ( int j = 0; j < value; j++ ) {
// str[ j ] = "0";
// }
// break;
// }
// }
// list.Add( str );
// }
// }
---------------------------------------------------------------------------------
もっと効率の良い(取り込んでから、格納までの消費メモリーや時間が短い)方法はないでしょうか。
結構、処理に時間がかかります。

引用返信 編集キー/
■44477 / inTopicNo.8)  Re[5]: C# XMLファイル形式の指定要素の属性値取得
□投稿者/ 渋木宏明(ひどり) (1259回)-(2009/12/09(Wed) 22:34:47)
渋木宏明(ひどり) さんの Web サイト
> Nullableの使い方をネットで調べましたが、Nullの場合は代用値を入れる 等の処理ができるようで、
> 使っていけそうですが、要素(ルート)自体がない場合には適用できなさそうですが、どうなんでしょうか?

使い方次第ではありますが、親要素が存在しないことまで表現するのはかなり難しいでしょうね。

そもそもで言えば、XML で表現されている階層構造のデータを、わざわざフラットな配列に押し込めようとしている時点で無理があるんです。

XML 中の Trackpoint タグと対応するデータクラスを定義して、XML の構造をデータクラスでほぼそのまま表現する方が楽だし使いやすいと思いますよ。

引用返信 編集キー/
■44486 / inTopicNo.9)  Re[6]: C# XMLファイル形式の指定要素の属性値取得
□投稿者/ Bianchi (9回)-(2009/12/09(Wed) 23:11:16)
No44477 (渋木宏明(ひどり) さん) に返信
>>Nullableの使い方をネットで調べましたが、Nullの場合は代用値を入れる 等の処理ができるようで、
>>使っていけそうですが、要素(ルート)自体がない場合には適用できなさそうですが、どうなんでしょうか?
>
> 使い方次第ではありますが、親要素が存在しないことまで表現するのはかなり難しいでしょうね。
>
> そもそもで言えば、XML で表現されている階層構造のデータを、わざわざフラットな配列に押し込めようとしている時点で無理があるんです。
>
> XML 中の Trackpoint タグと対応するデータクラスを定義して、XML の構造をデータクラスでほぼそのまま表現する方が楽だし使いやすいと思いますよ。
>

確かにおっしゃるとおりかと思います。といいますか、折角の階層構造データですから、本来はそのまま使いたいとは思ってますが、
使い方が良く分らないため、わかる方法→フラット配列に変換してる次第です。

もしよろしければ、どのようなコードを書けば良いのか教えていただけないでしょうか。
引用返信 編集キー/
■44800 / inTopicNo.10)  Re[7]: C# XMLファイル形式の指定要素の属性値取得
□投稿者/ Bianchi (11回)-(2009/12/17(Thu) 23:40:16)
とりあえずフラット配列で処理します

教授いただきありがとうございました
解決済み
引用返信 編集キー/


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

このトピックに書きこむ

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

管理者用

- Child Tree -