LoginSignup
1
0

More than 3 years have passed since last update.

Kinx ライブラリ - XML

Last updated at Posted at 2020-04-03

XML

News!

Kinx - 3rd Preview Release!

これまでの修正も含め、3rd Preview Release を行いました。ここで触れている Fiber の修正 も含まれてます。

しかし未だ プレビュー。もし宜しければバグ報告等頂けると大変助かります。特に今回の XML はあまりテストできていない感満載。もうちょっとテストできてから紹介しようかとも思ったものの、せっかくのプレビュー版で使い方が分からないのもどうかと思い公開することにしました。実装自体はしてあり、サンプルは動くことを確認済です。

はじめに

「見た目は JavaScript、頭脳(中身)は Ruby、(安定感は AC/DC)」 でお届けしているスクリプト言語 Kinx。言語はライブラリが命。ということでライブラリの使い方編。

今回は XML です。

XML もよく利用するのでスクリプト言語でサクッと扱いたい要素の一つ。

XML

DOMパース

Xml.parseFile() または Xml.parseString() を使って DOM ツリーを構築する。ファイルを読み込む場合は以下の通り。

var doc = Xml.parseFile("xmlfile.xml");

下記は文字列を直接パースする例。

var doc = Xml.parseString(%{
<?xml version="1.0" encoding="UTF-8" ?>
<artists>
  <artist country="US" id="1">
    <name>BON JOVI</name>
    <price>2400</price>
    <img file="bonjovi.jpg"/>
  </artist>
  <artist country="US" id="2">
    <name>GUNS N ROSES</name>
    <price>21000</price>
    <img file="GNR.jpg"/>
  </artist>
  <artist country="DE" id="3">
    <name>Helloween</name>
    <price>2400</price>
    <img file="helloween.jpg"/>
  </artist>
</artists>
});

返されたドキュメント・オブジェクトは以下のメソッドを持つ。

メソッド 内容
documentElement() ルートドキュメントを取得
createElement(tagname) Element ノードを作成する
createTextNode(text) Text ノードを作成する
createComment(comment) Comment ノードを作成する
createCdataSection(content) CDATA Section ノードを作成する
createProcessingInstruction(target, data) Processing Instruction ノードを作成する
createEntityReference(name) Entity Reference ノードを作成する
createElementNS(nsUri, qname) Element ノードを名前空間を指定して作成する
getElementById(id) id を指定してノードを検索する
getElementsByTagName(tagName) tagName のノードを配列にして返す
xpath(expr) expr の XPATH を評価し、結果を配列にして返す

ルートノード

ルートノードは documentElement() メソッドを使用して以下のように取得する。

var root = doc.documentElement();

XMLノード

ルートノードを含む XML ノードは以下のプロパティとメソッドを持つ。

プロパティ
プロパティ 内容
type ノード種別
name QName
tagName タグ名
localName ローカル名
namespaceURI 名前空間 URI
prefix プレフィックス
メソッド
メソッド 内容
attributes() 属性一覧を配列で返す。
setAttribute(qname, value) 属性を設定する。
setAttributeNS(nsUri, qname, value) 名前空間を指定して属性を設定する。
removeAttribute(qname) 属性を削除する。
removeAttributeNS(nsUri, localName) 名前空間を指定して属性を削除する。
parentNode() 親ノードを返す。
children() 子ノードを配列で返す。
firstChild() 最初の子ノードを返す。
lastChild() 最後の子ノードを返す。
nextSibling() 次のノードを返す。
previousSibling() 前のノードを返す。
appendChild(node) 子ノードにノードを追加する。
removeChild(node) 子ノードからノードを削除する。
replaceChild(node1, node2) 子ノードのノードを置き換える。
replaceNode(node) 自分自身のノードを別のノードでを置き換える。
insertBefore(node) 前のノードとしてノードを追加する。
insertAfter(node) 次のノードとしてノードを追加する。
remove() ノードを削除する。
textContent() テキストを取得する。
innerText() テキストを取得する。
hasChildren() 子ノードが存在すれば 1 を返す。
hasAttributes() 属性があれば 1 を返す。
getElementById(id) id を指定してノードを検索する
getElementsByTagName(tagName) tagName のノードを配列にして返す
xpath(expr) expr の XPATH を評価し、結果を配列にして返す

XPath

XPath は XPATH 式にマッチしたノードをノードセット(配列)の形で返す。ノードセットにも xpath() メソッドがあり、絞り込んだノード群に対し XPATH をチェインして使うことができる。

先ほどのサンプル XML のドキュメントに対して実行。

var nodes = doc.xpath("//artist")
               .xpath("price")
               .map(&(p) => p.innerText());

nodes.each(&(text) => {
    System.println(text);
});

結果。

2400
21000
2400

サンプル・ソース

同梱しているサンプルソースを載せておきます。説明していない Xml.Writer とかありますが、こんな感じの DOM パースができる例ということで、参考になると思い。

function displayXml(doc, node, indent) {
    System.print("  " * indent);
    if (node.type == Xml.ELEMENT_NODE) {
        System.print("ELEM %s" % node.name);
    } else if (node.type == Xml.TEXT_NODE) {
        System.print("TEXT %s" % node.value.trim());
    }

    var attr = node.attributes();
    for (var i = 0, len = attr.length(); i < len; ++i) {
        System.print("[%s=%s]" % attr[i].name % attr[i].value);
    }
    System.println("");

    var child = node.firstChild();
    while (child) {
        displayXml(doc, child, indent + 1);
        child = child.nextSibling();
    }
}

var doc = Xml.parseString(%{
<?xml version="1.0" encoding="UTF-8" ?>
<artists>
  <artist country="US" id="1">
    <name>BON JOVI</name>
    <price>2400</price>
    <img file="bonjovi.jpg"/>
  </artist>
  <artist country="US" id="2">
    <name>GUNS N ROSES</name>
    <price>21000</price>
    <img file="GNR.jpg"/>
  </artist>
  <artist country="DE" id="3">
    <name>Helloween</name>
    <price>2400</price>
    <img file="helloween.jpg"/>
  </artist>
</artists>
});
var root = doc.documentElement();
displayXml(doc, root);

var el = root.getElementById("3");
if (el) {
    el.remove();
}

System.println("");
System.println("getElementByTagName:");
var els = root.getElementsByTagName("img");
if (els.isArray) {
    els.each(&(el) => displayXml(doc, el));
}

System.println("");
System.println("XPath:");
var nodes = doc.xpath("//artist").xpath("price");
if (nodes.isArray) {
    nodes.each(&(el) => displayXml(doc, el));
}

var xmlWriter = new Xml.Writer(System);
xmlWriter.write(doc);
xmlWriter.write(root);

実行結果。

ELEM artists
  TEXT
  ELEM artist[country=US][id=1]
    TEXT
    ELEM name
      TEXT BON JOVI
    TEXT
    ELEM price
      TEXT 2400
    TEXT
    ELEM img[file=bonjovi.jpg]
    TEXT
  TEXT
  ELEM artist[country=US][id=2]
    TEXT
    ELEM name
      TEXT GUNS N ROSES
    TEXT
    ELEM price
      TEXT 21000
    TEXT
    ELEM img[file=GNR.jpg]
    TEXT
  TEXT
  ELEM artist[country=DE][id=3]
    TEXT
    ELEM name
      TEXT Helloween
    TEXT
    ELEM price
      TEXT 2400
    TEXT
    ELEM img[file=helloween.jpg]
    TEXT
  TEXT

getElementByTagName:
ELEM img[file=bonjovi.jpg]
ELEM img[file=GNR.jpg]

XPath:
ELEM price
  TEXT 2400
ELEM price
  TEXT 21000
<artists>
        <artist country="US" id="1">
                <name>BON JOVI</name>
                <price>2400</price>
                <img file="bonjovi.jpg" />
        </artist>
        <artist country="US" id="2">
                <name>GUNS N ROSES</name>
                <price>21000</price>
                <img file="GNR.jpg" />
        </artist>
</artists>
<artists>
        <artist country="US" id="1">
                <name>BON JOVI</name>
                <price>2400</price>
                <img file="bonjovi.jpg" />
        </artist>
        <artist country="US" id="2">
                <name>GUNS N ROSES</name>
                <price>21000</price>
                <img file="GNR.jpg" />
        </artist>
</artists>

おわりに

XPath が使えると便利だ。

そして、XML と Zip(以前の記事)を組み合わせると、実は Xlsx ファイル(Excel ファイル)の読み書きができたりします。Xlsx ファイルは Office Open XML という名前で標準仕様化されており(色々問題もあるが)、XML ファイルを Zip で固めたものになってるので読めたりするといった具合。

ただ、実際問題として Office Open XML の全てをサポートするってのは相当量のコードになるので、すぐにできそうなのは簡易的な読み書きくらいですね。時間があればチャレンジしよう。

ではまた次回。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0