XMLでの更新やソートなど

投稿者:アーク <info.nds.laboratry あっとまーくgmail.com> 投稿日:2019/02/04(Mon) 19:00:55 No.2367

こんばんは。アークです。

お世話になります。

さて、データファイルとしてCSVを使う事が多かったのですが、
最近、XMLを使い始めました。
単なる読み書きは問題無く行えるようになりましたが、
幾つかやり方が分からなく困っています。

1. 下記のXML文書にて内容の更新はどのように行うのでしょうか。
 例えば『りんご』を『苺』に替えたり『80』を『120』に変更する場合です。
 
2. 予めコードを振って置いてアクセスする事は可能でしょうか。
 例えば『<果物>』を『<果物 番号="1">』、『<果物 番号="2">』・・・の様にして置いて、
 その『番号』を頼りにアクセルしたい場合です。
 
3. 上記の様にコードが振られたXML文書をソートする事は可能でしょうか。

ご存知の方、よろしくお願いします。

-----------------------------------------------
<?xml version="1.0" encoding="utf-8"?>
<果物一覧>
<果物>
<名前>みかん</名前>
<値段 単位="円">50</値段>
</果物>
<果物>
<名前>りんご</名前>
<値段 単位="円">80</値段>
</果物>
</果物一覧
-----------------------------------------------

1に関しては…

投稿者:アーク <info.nds.laboratry あっとまーくgmail.com> 投稿日:2019/02/05(Tue) 10:02:22 No.2368

おはようございます。アークです。

1に関しては『《更新元》を《内容》へ《自分》から内容更新』を参考に、
『要素の「名前」の内容を「苺」へデータから内容更新』等と遣ってみましたが、
指定方法が間違っているのか変更されませんでした。

只、XML専用に用意された命令ではない下記の様な方法なら変更が可能でした。
スマートとは言えませんが…。

---------------------------------------------------------------------------------
ーーXMLを初期化
データは、「[プログラムの位置]くだもの.xml」をXMLとして開いたもの

ーー<果物一覧>タグを挿入する
果物一覧は、ルート要素

一覧は、「果物一覧\果物」をデータから得る
一覧を要素にそれぞれ繰り返す
  もし要素の「名前」の内容が「りんご」なら
    要素の「名前」の内容を「苺」に変える
  もし終わり
  要素の内容を報告する
繰り返し終わり

ーーXMLに書き出す
「[プログラムの位置]くだもの.xml」にデータを保存する
---------------------------------------------------------------------------------

Re: 1に関しては…

投稿者:通り道 投稿日:2019/02/06(Wed) 23:01:29 No.2369

こんにちは。
XML関連の命令は、デザイナの機能から見える命令と、マニュアルに記載の
命令がどうも対応がよくわかりませんでした。
プロデルのXMLの命令は、標準的なXPathを受け付けるものと、
プロデル独自のXMLパスもしくは選択パスと呼んでいるものがあるようです。
プロデル独自の方は、マニュアルの記載も少なく説明もないので
内容(テキストノード)を検索条件とするようなものはわかりませんでしたが、
XPathならば、いろいろなサイトに情報を参考にしてなんとかなりました。
※「/」区切りが効く命令はXPathで、「\」区切りが効く命令は選択パスなので、
 命令を試すことで区別はつきます。
以下のいずれかの命令で、「名前」のXML要素が取得できるので、
それに対して内容を更新する という形になるようです。
(内容更新の命令は、XPathではないようなのでだめっぽいです)
------
要素一覧は、データから「「/果物一覧/果物/名前[text()="りんご"]」」という要素をすべて取得する
単要素は、データから「「/果物一覧/果物/名前[text()="りんご"]」」という要素を取得する
------
前者は、結果がXML要素の配列になります。後者は、結果がXML要素です。
要素を取得できていたら、それぞれ、以下の命令で更新できます。
------
要素一覧(1)の内容を「苺」に変える
単要素の内容を「苺」に変える
------
どちらの命令の場合でも、データに保存されているXML文章のXML要素を更新しているため、データの内容も更新されます。

蛇足。
----
単要素は、データから「「/果物一覧/果物/名前[text()="りんご"]/..」」という要素を取得する
----
とすると、名前の内容がリンゴとなる要素の、1つ親の要素(果物)を取得できます。
さらに、
----
単要素は、データから「「/果物一覧/果物/名前[text()="りんご"]/../値段」」という要素を取得する
----
とすれば、りんごの値段の要素を取得したりもできます。
また、仮に、xmlが、以下のようになっている場合、
----
<果物>
<名前>りんご</名前>
<値段 単位="円">80</値段>
<値段 単位="$">0.50</値段>
</果物>
----
以下のようなことも可能です。
----
単要素は、データから「「/果物一覧/果物/名前[text()="りんご"]/../値段[@単位="$"]」」という要素を取得する
----
また、本来は、XPathによる取得(検索)は、XML全体でも各要素からでも
行えるはずなのですが、プロデルではXML文章からしかたどれないようですので、
再帰的にループして絞り込むような場合にはちょっと不便かもしれません。

通り道 さん

投稿者:アーク <info.nds.laboratry あっとまーくgmail.com> 投稿日:2019/02/07(Thu) 17:49:04 No.2370

こんばんは。お世話になります。アークです。

コメントありがとうございます。

XMLはVBSで少し使ってみた程度ですが、
その時の知識も役に立たず困っていました。
早速やってみたところピンポイントで指定できる事を確認しました。
これでプロデルでもXMLが使えるようになったので先に進めそうです。

色々と教えて頂きありがとうございました。

要素を削除するには

投稿者:アーク <info.nds.laboratry あっとまーくgmail.com> 投稿日:2019/02/08(Fri) 23:29:58 No.2373

こんばんは。アークです。

通り道さんのお蔭で1は解決しました。
また、その延長で2も解決しました。
3に関しては目視の問題なのでプログラム的には緊急度は高く有りません。

しかし、また新たな問題に遭遇してしまいました。
1で要素を特定して置いて削除しようとしたのですが、
色々と試してみたものの要素の削除に成功していません。

4. 要素を削除するにはどのようにすれば良いのでしょうか。

データから「/果物一覧/果物/名前[text()="りんご"]」を削除する
と化では駄目でした。

お分かりの方、よろしくお願いします。

Re: 要素を削除するには

投稿者:通り道 投稿日:2019/02/10(Sun) 02:23:42 No.2375

こんにちは。
少し試してみたのですが、xpathを使用して削除する方法はないようです。
また、削除は、XML文章にしか手順がなく、親となる要素や対象の要素を
取得してから・・・ということもできないようです。
そのため、プロデル独自の、選択パスを使用して目的の要素をXML文章から
直接特定する必要があります。
※なお、プロデルは、XML要素から、親要素にたどる手順や項目はないようです。

今の状態では、削除対象を選択パスで特定できないため、XMLを少し変更します。
削除したい要素に、それを区別できるよう、属性を付加します。
(このとき、名前に属性を付けても、名前の要素しか削除できません)
--------
<?xml version="1.0" encoding="utf-8"?>
<果物一覧>
<果物 nm="みかん">
<名前>みかん</名前>
<値段 単位="円">50</値段>
<値段 単位="$">0.25</値段>
</果物>
<果物 nm="りんご">
<名前>りんご</名前>
<値段 単位="円">80</値段>
<値段 単位="$">0.50</値段>
</果物>
</果物一覧>
-----
そのうえで、以下のように選択パスで指定します。
----
「果物一覧\果物@nm=りんご」をデータから削除
----
(@を付加すると属性を表すというのは、XPathと似ています)
選択パスは、XPathとだいたい似ていますが、以下が違うようです。
・区切り文字が「/」ではなく「\」
・先頭に「\」がない。常に手順を実行するインスタンス基準となる。
・途中階層を省略できない。XPathには、「//」とすると、
 その部分は任意の階層数とマッチする(先頭でも途中でも使える)。
 (xpathの場合、「//名前」として、任意の階層にある「名前」要素の列挙ができる)
・属性で判定する際に、名前のワイルドカードがない
 XPathでは、「*」がある。
 (選択パスの値段@=$は、xpathでは値段[@="$"]ですが、*[@="$"]も使えます)
・要素のフィルタリングとして、属性に対する=しか無い と思われる。
・パス中で指定可能な相対要素がない。xpathには親要素や次/前の兄弟要素を
 指定する方法がある(特定の要素の次の要素 とかも1度で抽出できる)
また、選択パスで取得しよとした場合に、マッチするものが複数ある場合、
取得しようとしている要素の階層そのものが複数ある場合(親要素が共通の場合)には
それらを配列として取得できるのですが、親要素が異なるものがある場合には、
親要素が共通となる範囲でしか配列に含まれません。例えば、以下です
----
項目は、「果物一覧\果物」をデータから得る ' 2つ取得される
項目は、「果物一覧\果物\名前」をデータから得る ' 1つだけ取得される
----

おすすめの方法は、ドットネット機能を使用して、System.Xml.*を
直接利用する方法です。必要となる機能だけをラッピングした種類を
作成して、plugin化して利用するのが良いと思ます。

Re^2: 要素を削除するには

投稿者:アーク <info.nds.laboratry あっとまーくgmail.com> 投稿日:2019/02/10(Sun) 22:38:30 No.2376

通り道 さん

こんばんは。お世話になります。アークです。

〉少し試してみたのですが、xpathを使用して削除する方法はないようです
やはりそうだったのですね。

〉なお、プロデルは、XML要素から、親要素にたどる手順や項目はないようです
要素の親とか遣っても駄目な訳ですね。

〉「果物一覧\果物@nm=りんご」をデータから削除
こちらの方法で中身だけではなく要素自体が削除される事を確認しました。

〉plugin化して利用するのが良いと思ます
引数を伴った手順の作成やplugin化は未だ成功した試しが有りません。
前者は多分、助詞とかの使い方を理解していない為と思われます。
後者は例えば通り道 さんに作成して頂いたアイコン抽出のソースを、
抽出部分とそれを利用するプログラムを切り分けてからplugin化してみたのですが、
「その手順は有りません」といった内容のエラーで作成できませんでした。
プロデルを始めて1年が経つというのにまだこの有様です。

いい加減にCSVから卒業してXMLを使おうと思ったのですが、
プロデルでXMLを自在に使うのは結構大変そうですね。
もう少し大規模なデータなら迷わずにデータベースを使う処なのですが…。

お陰様で大分先に進む事ができました。
いつもありがとうございます。<m(_ _)m>

▲ページの先頭へ

- WebForum -