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

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

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

Re[4]: Xml要素の挿入について


(過去ログ 133 を表示中)

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

■78764 / inTopicNo.1)  Xml要素の挿入について
  
□投稿者/ Muu (2回)-(2016/02/15(Mon) 17:48:57)

分類:[.NET 全般] 

2016/02/15(Mon) 17:59:36 編集(投稿者)
Win7 32/64bit Vs2015 C# .Net3.5〜

お世話になります。Xmlファイルに対して以下のような編集を実現したいです。

-<編集前>----------------------------------------------
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <Framework>
    <DebugMode Value="false" />
    <Path Value="C:\test" />
  </Framework>
</configuration>

-<編集後>----------------------------------------------
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <Framework>
    <DebugMode Value="false" />
    <DebugMode2 Value="false" />   ←挿入
    <DebugMode3 Value="false" />   ←挿入
    <Path Value="C:\test" />
  </Framework>
</configuration>

※DeBugModeとPathの間にDebug2、Debug3を挿入する。


読み込んだ編集前のXmlデータはツリービュー上でツリー構造
で表示しています。また、TreeNodeのTagにXmlNodeを紐付けて
ツリーノード選択時に対応するXmlNodeを取得できるようにし
ています。


挿入したいXml要素は画面上のテキストボックス上に直接Xml形式で
入力します。

-<挿入対象:テキストボックスに記載>----------------
<DebugMode2 Value="false" />
<DebugMode3 Value="false" />
---------------------------------------------------

以下、コード


-<Xml初期読み込み>---------------------------------
XmlDocument m_xmlDocument; 
m_xmlDocument.Load(xmlFile);


-<要素挿入処理:Button_Click>----------------------
//○追加対象をドキュメントオブジェクトに作成
XmlDocument xdocNew = new XmlDocument();
xdocNew.InnerXml = "<Root>\n" + rtText.Text + "\n" + "</Root>";
XmlNode xnAddNewRoot = xdocNew.FirstChild;

//○参照ノード取得(追加位置)
XmlNode refNode = (XmlNode)tvXml.SelectedNode.Tag;

//○全要素をループ処理
for (int i = xnAddNewRoot.ChildNodes.Count-1; i>=0; i--)
{
	XmlNode xnNewNode = xnAddNewRoot.ChildNodes[i];

	//追加対象をXmlElementとして作成
	XmlElement xmlNewElement = m_xmlDocument.CreateElement(xnNewNode.Name);
	xmlNewElement.InnerXml = xnNewNode.InnerXml;

	try
	{
		XmlNode AddedNode = m_xmlDocument.DocumentElement.InsertBefore(xmlNewElement, refNode);
		refNode = AddedNode;		//参照ノードを更新
	}
	catch (Exception err)
	{
		MessageBox.Show(err.Message.ToString());
	}
	xnNewNode = xdocNew.NextSibling;
}
---------------------------------------------------------


上記のコードを元に
<DebugMode2 Value="false" />
<DebugMode3 Value="false" />

の挿入を試したところ

@「<Framework>」を選択して挿入した場合
 「<Framework>」の前に挿入できた。
 ※但し、上記コードではValueはまだ取り込んでません。

A「<Path Value="C:\test" />」を選択して挿入した場合

 catchブロックにて「参照ノードはこのノードの子ではありません。」
 のエラーが表示される。


上記のようになります。
Aのエラーをどのようにすれば回避して、意図した編集ができるでしょうか。


以上、よろしくお願いします m(__)m。


引用返信 編集キー/
■78769 / inTopicNo.2)  Re[1]: Xml要素の挿入について
□投稿者/ 魔界の仮面弁士 (646回)-(2016/02/15(Mon) 21:20:22)
2016/02/15(Mon) 21:28:28 編集(投稿者)

No78764 (Muu さん) に返信
> Xmlファイルに対して以下のような編集を実現したいです。
Linq 対応の System.Xml.Linq.XDocument ではなく、
従来からの System.Xml.XmlDocument の場合ですね。


> 挿入したいXml要素は画面上のテキストボックス上に直接Xml形式で
> 入力します。
> -<挿入対象:テキストボックスに記載>----------------
> <DebugMode2 Value="false" />
> <DebugMode3 Value="false" />
> ---------------------------------------------------

XML というか、ノードリストですね。


> XmlNode xnAddNewRoot = xdocNew.FirstChild;
これでも取得できますが、ルート要素を取得する場合は、
DocumentElement プロパティの方が適切かと思います。



> @「<Framework>」を選択して挿入した場合
>  「<Framework>」の前に挿入できた。
>  ※但し、上記コードではValueはまだ取り込んでません。

こういう結果になるということですね。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
 <DebugMode2 />
 <DebugMode3 />
 <Framework>
  <DebugMode Value="false" />
  <Path Value="C:\test" />
 </Framework>
</configuration>


> ※DeBugModeとPathの間にDebug2、Debug3を挿入する。
だとすれば、こうかな。

// XmlNode refNode = m_xmlDocument.SelectSingleNode("/configuration/Framework");
XmlNode n = refNode.FirstChild;
foreach (XmlNode node in xnAddNewRoot.ChildNodes)
{
  n = n.ParentNode.InsertAfter(m_xmlDocument.ImportNode(node, true), n);
}


> A「<Path Value="C:\test" />」を選択して挿入した場合

だとすれば、こうかな。


// XmlNode refNode = m_xmlDocument.SelectSingleNode("/configuration/Framework/Path");
foreach (XmlNode node in xnAddNewRoot.ChildNodes)
{
  refNode.ParentNode.InsertBefore(m_xmlDocument.ImportNode(node, true), refNode);
}
引用返信 編集キー/
■78776 / inTopicNo.3)  Re[2]: Xml要素の挿入について
□投稿者/ Muu (3回)-(2016/02/16(Tue) 09:05:23)
魔界の仮面弁士様
いつもありがとうございます。

>>XmlNode xnAddNewRoot = xdocNew.FirstChild;
> これでも取得できますが、ルート要素を取得する場合は、
> DocumentElement プロパティの方が適切かと思います。
なるほど、了解です。

> こういう結果になるということですね。
はい、その内容になっていました。

> // XmlNode refNode = m_xmlDocument.SelectSingleNode("/configuration/Framework");
> XmlNode n = refNode.FirstChild;
> foreach (XmlNode node in xnAddNewRoot.ChildNodes)
> {
>   n = n.ParentNode.InsertAfter(m_xmlDocument.ImportNode(node, true), n);
> }

この方法を試したところ、選択ノードがコメントの場合、パスが
「/configuration/#comment」のようになり、m_xmlDocument.SelectSingleNodeで
エラーがでました。
パスはXmlNodeのNameプロパティを連結して作成してます。
パスの作り方がまずいでしょうか。

なので、この部分はTreeNodeのTagに設定してあるXmlNodeを使用しました。

最終的にはソースは以下のようになりました。

-------------------------------
//○追加対象をドキュメントオブジェクトに作成
XmlDocument xdocNew = new XmlDocument();
xdocNew.InnerXml = "<Root>\n" + rtText.Text + "\n" + "</Root>";
XmlNode xnAddNewRoot = xdocNew.DocumentElement;

try
{
	XmlNode refNode = (XmlNode)tvXml.SelectedNode.Tag;

	foreach (XmlNode node in xnAddNewRoot.ChildNodes)
	{
		refNode.ParentNode.InsertBefore(m_xmlDocument.ImportNode(node, true), refNode);
	}
}
catch (Exception err)
{
	MessageBox.Show(err.Message.ToString());
}
-------------------------------


あと、ご返信いただく直前に試行錯誤していて、XPathNavigatorでもなんだかいけそうかなぁという感じ
がありました。

XmlNode refNode = (XmlNode)tvXml.SelectedNode.Tag;
XPathNavigator navigator = refNode.CreateNavigator();
navigator.InsertBefore(rtText.Text);


どうもありがとうございましたm(__)m。

解決済み
引用返信 編集キー/
■78777 / inTopicNo.4)  Re[3]: Xml要素の挿入について
□投稿者/ 魔界の仮面弁士 (647回)-(2016/02/16(Tue) 10:22:48)
No78776 (Muu さん) に返信
> なので、この部分はTreeNodeのTagに設定してあるXmlNodeを使用しました。
や。それで OK です。
こちらで検証する際には、わざわざ TreeNode を構築していられないので、
掲示板投稿時には、XPath で代用したというだけのことです。

> xdocNew.InnerXml = "<Root>\n" + rtText.Text + "\n" + "</Root>";
最初が「"<Root>\n"」なら、最後も「"\n</Root>"」で良い気が。

それはさておき、今回は 2015 なので、
 xdocNew.InnerXml = $"<Root>\n{rtText.Text}\n</Root>";
と書けますよ。



> MessageBox.Show(err.Message.ToString());
Message プロパティは String 型ですよね。
それをさらに ToString している意図はなんですか?
解決済み
引用返信 編集キー/
■78779 / inTopicNo.5)  Re[4]: Xml要素の挿入について
□投稿者/ Muu (4回)-(2016/02/16(Tue) 13:51:05)
魔界の仮面弁士様

> や。それで OK です。
> こちらで検証する際には、わざわざ TreeNode を構築していられないので、
> 掲示板投稿時には、XPath で代用したというだけのことです。
了解です。XPathの使い方の勉強になりました。


>>xdocNew.InnerXml = "<Root>\n" + rtText.Text + "\n" + "</Root>";
> 最初が「"<Root>\n"」なら、最後も「"\n</Root>"」で良い気が。
あ・・・・なぜこのような記載をw

>
> それはさておき、今回は 2015 なので、
>  xdocNew.InnerXml = $"<Root>\n{rtText.Text}\n</Root>";
> と書けますよ。
ほぇ〜、こんな記述ができるようになったんですね。


>>MessageBox.Show(err.Message.ToString());
> Message プロパティは String 型ですよね。
> それをさらに ToString している意図はなんですか?

あ、あれ?String型!! ほんとだ・・・
えっと、勘違い(^^;;

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


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

このトピックに書きこむ

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

管理者用

- Child Tree -