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

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

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

Re[1]: C#でXMLを書き換える


(過去ログ 120 を表示中)

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

■70377 / inTopicNo.1)  C#でXMLを書き換える
  
□投稿者/ OROCHI (26回)-(2014/03/17(Mon) 20:57:11)

分類:[C#] 

こんにちは
現在以下の様なXMLがあるとします

<?xml version="1.0" encoding="utf-8">
<manifest XX/>
<action ab:cd="01" value = "false" />
<action wx:yz="02" value = "true" />
</manifest>

ここで<action ab:cd="01" value = "false" />の"false"の部分を"true"に書き換えるようなプログラムを作りたいのですが、このような場合どのようなコードを書いたら良いのでしょうか?
XMLをC#で取り扱うのが何分初めてなので、できればサンプルなどがあるとありがたいです
引用返信 編集キー/
■70379 / inTopicNo.2)  Re[1]: C#でXMLを書き換える
□投稿者/ 魔界の仮面弁士 (566回)-(2014/03/17(Mon) 21:31:24)
No70377 (OROCHI さん) に返信
> 現在以下の様なXMLがあるとします

文法が出鱈目で、XML になっていませんよ。(^^;

XML 宣言部が「?>」ではなく「>」で終わっているとか、
最初のmanifestの「XX/>」の部分とか、
ab や wx の名前空間が宣言されていないとか。


> <?xml version="1.0" encoding="utf-8">
> <manifest XX/>
> 	<action ab:cd="01" value = "false" />
> 	<action wx:yz="02" value = "true"  />
> </manifest>

とりあえず、下記のように補正します。

<?xml version="1.0" encoding="utf-8"?>
<manifest
 xmlns:ab="http://vb-user.net/xmlns/wankuma/70377/ab"
 xmlns:wx="http://vb-user.net/xmlns/wankuma/70377/wx">
	<action ab:cd="01" value="false" />
	<action wx:yz="02" value="true" />
</manifest>



> ここで<action ab:cd="01" value = "false" />の"false"の部分を"true"に書き換える

案1) System.Xml.Linq を用いる。

//var doc = XDocument.Load(@"C:\TEMP\test.xml");

var doc = XDocument.Parse(
@"<?xml version='1.0' encoding='utf-8'?>
<manifest
 xmlns:ab='http://vb-user.net/xmlns/wankuma/70377/ab'
 xmlns:wx='http://vb-user.net/xmlns/wankuma/70377/wx'>
	<action ab:cd='01' value='false' />
	<action wx:yz='02' value='true' />
</manifest>");

XNamespace nAB = "http://vb-user.net/xmlns/wankuma/70377/ab";

var q = from atr in doc.Root.Elements("action").Attributes(nAB + "cd")
        where atr.Value == "01"
        select atr.Parent.Attribute("value");

foreach (var item in q)
{
    if (item.Value == "false") item.Value = "true";
}

Console.WriteLine(doc.ToString());

//doc.Save(@"C:\TEMP\test2.xml");

引用返信 編集キー/
■70382 / inTopicNo.3)  Re[1]: C#でXMLを書き換える
□投稿者/ WebSurfer (198回)-(2014/03/17(Mon) 21:32:13)
No70377 (OROCHI さん) に返信
> XMLをC#で取り扱うのが何分初めてなので、できればサンプルなどがあるとありがたいです

この ↓ あたりから読んでいくことをお勧めします。

XML ドキュメント オブジェクト モデル (DOM)
http://msdn.microsoft.com/ja-jp/library/hf9hbf87(v=vs.100).aspx
引用返信 編集キー/
■70383 / inTopicNo.4)  Re[2]: C#でXMLを書き換える
□投稿者/ 魔界の仮面弁士 (567回)-(2014/03/17(Mon) 21:39:19)
No70379 (魔界の仮面弁士) に追記
> 案1) System.Xml.Linq を用いる。

案2)System.Xml の XmlDocument を用いる。

var doc = new XmlDocument();
//doc.Load(@"C:\TEMP\test.xml");

doc.LoadXml(
@"<?xml version='1.0' encoding='utf-8'?>
<manifest
 xmlns:ab='http://vb-user.net/xmlns/wankuma/70377/ab'
 xmlns:wx='http://vb-user.net/xmlns/wankuma/70377/wx'>
	<action ab:cd='01' value='false' />
	<action wx:yz='02' value='true' />
</manifest>");

var xmlnsManager = new XmlNamespaceManager(doc.NameTable);
xmlnsManager.AddNamespace("ab", "http://vb-user.net/xmlns/wankuma/70377/ab");

var atr = doc.SelectSingleNode("/manifest/action[@ab:cd='01']/@value", xmlnsManager);
if (atr != null && atr.Value == "false")  atr.Value = "true";

Console.WriteLine(doc.OuterXml);

doc.Save(@"C:\TEMP\test2.xml");

引用返信 編集キー/
■70395 / inTopicNo.5)  Re[1]: C#でXMLを書き換える
□投稿者/ OROCHI (28回)-(2014/03/20(Thu) 13:02:03)
2014/03/20(Thu) 13:51:51 編集(投稿者)
こんにちは、お返事ありがとうございました

ただ、案1も案2も実験では成功したのですが、実際に使う場合ではどちらも失敗でした
実際に使うxmlはAndroidソフトを作るときに使うマニフェストファイルで、以下のようなものです(最初から書いておけばよかったですね。すみません)


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="xxx.xxx.xxx" android:theme="@android:style/Theme.NoTitleBar" android:versionName="1.0" android:versionCode="1" android:installLocation="preferExternal">
  <supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" />
  <application android:icon="@drawable/app_icon" android:label="@string/app_name" android:debuggable="false">
    <activity android:label="@string/app_name" android:name="xxx.xxx.xxx.ImmersiveFullScreenActivity" android:screenOrientation="sensorLandscape" android:launchMode="singleTask" android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale">
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
      <meta-data android:name="unityplayer.UnityActivity" android:value="true" />
      <meta-data android:name="unityplayer.ForwardNativeEventsToDalvik" android:value="false" />
    </activity>
  </application>
  <uses-sdk android:minSdkVersion="9" android:targetSdkVersion="18" />
  <uses-feature android:glEsVersion="0x00020000" />
  <uses-permission android:name="android.permission.INTERNET" />
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  <uses-feature android:name="android.hardware.touchscreen" />
  <uses-feature android:name="android.hardware.touchscreen.multitouch" android:required="false" />
  <uses-feature android:name="android.hardware.touchscreen.multitouch.distinct" android:required="false" />
  <supports-gl-texture android:name="GL_OES_compressed_ETC1_RGB8_texture" />
</manifest>

書き換えたいのが
<meta-data android:name="unityplayer.ForwardNativeEventsToDalvik" android:value="false" />
の部分であり、ここのvalueをtrueにします

ということで、案1の場合は以下のように書いてみました
          var doc = XDocument.Load(path);
				XNamespace nAB="http://schemas.android.com/apk/res/android";

				var q = from atr in doc.Root.Elements("meta-data").Attributes(nAB + "name")
					where atr.Value == "unityplayer.ForwardNativeEventsToDalvik"
						select atr.Parent.Attribute("android:value");
				foreach (var item in q)
				{
					if(item.Value == "false")
						item.Value = "true";
				}
				doc.Save(path);
しかし、itemの値がnullになり失敗しました
案2の場合は以下のように書いてみました
          var doc = new XmlDocument();
				doc.Load(path);
  
				var xmlnsManager = new XmlNamespaceManager(doc.NameTable);
				xmlnsManager.AddNamespace("android","http://schemas.android.com/apk/res/android");
				var atr = doc.SelectSingleNode("/manifest/application/activity/meta-data[@android:name='unityplayer.ForwardNativeEventsToDalvik']/@value",xmlnsManager);
				if(atr != null && atr.Value == "false")
				{
					atr.Value = "true";
				}
				doc.Save(path);
こちらではatrの値がnullとなり失敗しました。
どちらにせよノードの構造がかなり複雑なので、私がパスの指定の方法を間違えた公算が高いのですが、それ以外にも原因があるのか、よろしければ教えていただけないでしょうか?

引用返信 編集キー/
■70397 / inTopicNo.6)  Re[2]: C#でXMLを書き換える
□投稿者/ Hongliang (184回)-(2014/03/20(Thu) 14:06:48)
2014/03/20(Thu) 14:08:58 編集(投稿者)
> var q = from atr in doc.Root.Elements("meta-data").Attributes(nAB + "name")
> 	where atr.Value == "unityplayer.ForwardNativeEventsToDalvik"
> 	select atr.Parent.Attribute("android:value");
> しかし、itemの値がnullになり失敗しました

Elements拡張メソッドは子要素だけを列挙するメソッドです。
子孫要素を列挙したいならDescendents拡張メソッドを使用します。
また、valueの指定が間違っています。nAB + "value"とする必要があります。

> var atr = doc.SelectSingleNode("/manifest/application/activity/meta-data[@android:name='unityplayer.ForwardNativeEventsToDalvik']/@value",xmlnsManager);
> こちらではatrの値がnullとなり失敗しました。

value属性もandroid接頭辞の名前空間下ですが、XPathでは名前空間接頭辞が指定されていません。

引用返信 編集キー/
■70398 / inTopicNo.7)  Re[3]: C#でXMLを書き換える
□投稿者/ 魔界の仮面弁士 (568回)-(2014/03/20(Thu) 14:40:58)
No70397 (Hongliang さん) に返信
>> var q = from atr in doc.Root.Elements("meta-data").Attributes(nAB + "name")
> 子孫要素を列挙したいならDescendents拡張メソッドを使用します。

Descendents ではなく、Descendants ですね。


もし Elements で辿るなら、それぞれの階層を指定することになります。

var q = from atr in doc.Root.Elements("application")
            .Elements("activity").Elements("meta-data")
            .Attributes(nAB + "name")
        where …

なお <meta-data> 要素は <activity> 配下のほか、
<service> 要素や <receiver> 要素などの下にも出現する可能性があります。


>>var atr = doc.SelectSingleNode("/manifest/application/activity/meta-data[@android:name='unityplayer.ForwardNativeEventsToDalvik']/@value",xmlnsManager);
>>こちらではatrの値がnullとなり失敗しました。
> value属性もandroid接頭辞の名前空間下ですが、XPathでは名前空間接頭辞が指定されていません。

つまり、/@value ではなく、/@android:value ということになります。

また、もしも名前空間を無視して、とにかく "value" という属性名として指定したいなら、
/@*[local-name()='value'] という XPath を指定することができます。


ちなみに、上記の応用で名前空間まで指定する場合は
/@*[local-name()='value' and namespace-uri()='http://schemas.android.com/apk/res/android']
もしくは
/@*[namespace-uri()='http://schemas.android.com/apk/res/android'][local-name()='value']
のようにも書けます。あまり使わない書き方とは思いますが、一応参考までに。

引用返信 編集キー/
■70402 / inTopicNo.8)  Re[1]: C#でXMLを書き換える
□投稿者/ OROCHI (30回)-(2014/03/20(Thu) 17:35:49)
ありがとうございました
以下のような書き方でなんとかなりました      

                                var xmlnsManager = new XmlNamespaceManager(doc.NameTable);
				xmlnsManager.AddNamespace("android","http://schemas.android.com/apk/res/android");
				var atr = doc.SelectSingleNode("/manifest/application/activity/meta-data[@android:name='unityplayer.ForwardNativeEventsToDalvik']/@android:value",xmlnsManager);
				if(atr != null && atr.Value == "false")
				{
					atr.Value = "true";
				}

解決済み
引用返信 編集キー/


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

このトピックに書きこむ

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

管理者用

- Child Tree -