« 異体字 | トップページ | XMLのコメント »

2019年8月21日 (水)

階層の深いXMLに要素を挿入

昨日の夜中、不意打ちをくらった。

突然の落雷。
バリバリ~~って。

いやぁ、ビックリビックリ。

お昼くらいまでは曇りで、午後から太陽がちょっと見えた。

気温はそんなに上がっていなくても、ムッシムッシだね。

 

僕は、Windowsのソフトウェアを作る時は、VB.NETのVisual Basicを使う。
設定ファイルは、昔からの流れで、INIファイル。
やっぱりINIファイルの方が、見た目はわかりやすいし、直接ファイルを触る時も扱いやすい。

日本語や英語だけの環境であれば、Shift-JISでいいのだけれど、多言語、つまり、ユニコード対応となると、Shift-JISでは出来ない。
UTF-8でいけるか?と思ったけれど、それはダメで、なんとまぁ、「UTF-16LE BOM付き」のテキストファイルである必要性がある。

新しくプログラムを作る時、先人が残してくれたINIファイル読み書きClassを流用する。
ただ、これがちょっと面倒。

随分前から、VB.NETでは、XMLファイルで設定ファイルを作ることを推奨している。
そうすれば、「UTF-8 BOM付き」で扱える。

一度作ってしまえば、UTF-8だろうが、UTF-16LEだろうが、あまり関係ないのだけれど、気分的には、UTF-8の方がいいかな。(笑)

ただ、XMLって、あのタグというのが仰々しいんだよねぇ。
だから、敬遠していた。食わず嫌いだ。(苦笑)

ひょんなことから、XMLファイルを探求してみようと思って、色々とやってみた。

XMLとXSL。それをHTML化にする、とか。
だいたいXMLというものがわかったので、VB.NETでもXMLを扱ってみることにした。

なんとまぁ、わかってしまえば、INIファイルより、読み書きはとても簡単!
(一つ問題点はあるんだけれど、それは今回の件とは関係ないので、割愛。)
いくつかのライブラリーをインポートするだけでいい。INIファイルを読み書きする時の準備より楽だった。

でも、一つだけはまってしまったことがあった。
調べても適当な情報が出てこなかったので、今回は、それについて残しておこうと思う。

何にはまったか?
題名の通り、「階層の深いXMLに要素を挿入」すること。
追加というより、挿入の方が言葉は相応しいかな、と。

設定ファイルとしてXMLを使う場合、そんなに深い階層にはしないので、僕が今回やったことはイレギュラーかもしれないけれど、XMLをデータベースやテーブル的に使う場合は、深い階層にすることもあるかもしれない。

ルート直下に追加するのは簡単だったのだけれど、こういうXMLに要素を挿入するという情報があまりなかったのである。

<?xml version="1.0" encoding="utf-8"?>
<Level1>
  <Level2>
    <Level3>
      <Level4>
        <Level5>
          <Level6>
            <L6child11>kkk</L6child11>
            <L6child12>lll</L6child12>
          </Level6>
        </Level5>
        <L4child1>aaa</L4child1>
        <L4child2>bbb</L4child2>
      </Level4>
    </Level3>
  </Level2>
</Level1>

こんなの、本当にイレギュラーだ。(苦笑)

ある情報を見ていて、そういうこと?ということに気付いて、問題解決!
そのソースがこれ。

Dim path As String = "xmladd.xml"

Dim xDoc = XElement.Load(path)

'Level4直下に、新たな子を追加
Dim Level4 = xDoc.XPathSelectElement("Level2/Level3/Level4")
Dim Xmlele As XElement =
    <L4child3>ccc🦌</L4child3>
Level4.Add(Xmlele)

'Level6直下に、新たな子を追加
Dim Level6 = xDoc.XPathSelectElement("Level2/Level3/Level4/Level5/Level6")
Xmlele = New XElement("L6child13", "mmm🚛")
Level6.Add(Xmlele)

'Level6直下に、新たなレベルとその子を追加
Xmlele =
    <Level7a No="555" Addr="33">
    <L7achild1>1</L7achild1>
    <L7achild2>2</L7achild2>
    </Level7a>
Level6.Add(Xmlele)

'Level6直下に、新たなレベルとその子を追加
Dim Num = "88"
Xmlele = New XElement("Level7b",
    New XAttribute("No", "777"),
    New XAttribute("Addr", Num),
    New XElement("L7bchild7a", "sss☑"),
    New XElement("L7bchild7b", "ttt🔣")
)
Level6.Add(Xmlele)

xDoc.Save(path)

予め、「Imports System.Xml」「Imports System.Xml.XPath」はしておこう。

やっていることは、Level4とLevel6に、要素を追加すること。

結果がこれ。

<?xml version="1.0" encoding="utf-8"?>
<Level1>
  <Level2>
    <Level3>
      <Level4>
        <Level5>
          <Level6>
            <L6child11>kkk</L6child11>
            <L6child12>lll</L6child12>
            <L6child13>mmm🚛</L6child13>
            <Level7a No="555" Addr="33">
              <L7achild1>1</L7achild1>
              <L7achild2>2</L7achild2>
            </Level7a>
            <Level7b No="777" Addr="88">
              <L7bchild7a>sss☑</L7bchild7a>
              <L7bchild7b>ttt🔣</L7bchild7b>
            </Level7b>
          </Level6>
        </Level5>
        <L4child1>aaa</L4child1>
        <L4child2>bbb</L4child2>
        <L4child3>ccc🦌</L4child3>
      </Level4>
    </Level3>
  </Level2>
</Level1>

太字のものが挿入されたもの。絵文字は意味なし。ユニコードなので、入れてみただけ。(笑)

ポイントは、「XPathSelectElement」での指定の仕方。
Level4を例にすると、上記では、
Dim Level4 = xDoc.XPathSelectElement("Level2/Level3/Level4")
と、書いている。

気が付いただろうか?
普通に考えれば、
Dim Level4 = xDoc.XPathSelectElement("/Level1/Level2/Level3/Level4")
にすると思うよね?
つまり、ルートから指定する。

でも、どうやら、ルートは「当たり前」ということらしく、その次の要素から記述するようだ。

これに気付かず、なんでダメなんだ??と余計なことまで調べていたのである。(苦笑)

別に上記の書き方でもOKにしてくれていればいいのに、と思うのは僕だけではないはず。
いや、もしかして、XML的に、そういうルールでもあるのだろうか?

この情報があまりなかったので、残しておこうかな、と思って書いた次第。

いくつか要素を挿入しているけれど、「XElement」で宣言するやり方で、タグそのまま「<L4child3>ccc🦌</L4child3>」のように記述するやり方と、「New XElement("L7bchild7a", "sss☑"),」という形で記述するやり方も書いておいた。

これで、どんなに階層が深くても、どこにでも要素を挿入出来るよ!

|

« 異体字 | トップページ | XMLのコメント »

パソコン・インターネット」カテゴリの記事

コメント

コメントを書く



(ウェブ上には掲載しません)




« 異体字 | トップページ | XMLのコメント »