C++ ときどき ごはん、わりとてぃーぶれいく☆

USAGI.NETWORKのなかのひとのブログ。主にC++。

逆引き風 roxmltree の基礎的な使い方のメモ; rust のたぶん今の所いちばん速くて安全な XML ぱーさー

note: このメモは roxmltree-0.13.0 の時代に書きました。

はじめに知っておくとよいこと

  • 与えられた XMLDocumentNode木構造に分解して Node を基準に操作するための crate = roxmltree
  • NodeXML の Element (≈タグ)とは限りません。 Node が出てきたらカモシレナイ match/if が必要なパターンがあります
    • NodeType::Root = Document (文書全体)
    • NodeType::Element = XML Element (要素≈タグ)
    • NodeType::PI = XML Processing Instruction (<?xml ?> とか <?hogehoge ?> 的なタグもどきのやつ)
    • NodeType::Comment = XML Comment (コメント)
    • NodeType::Text = XML Text (テキスト≈<tag>abc</tag>abcの部分)
  • ancestor は上位(先祖)、 sbling は同位(姉妹)、 descendant は下位(子孫)
  • parent は直近の上位(親)、 child は直近の下位(子)

XMLを開く

let document: roxmltree::Document = roxmltree::Document::parse( "<root/>" );

XMLのルート要素の Node を取得する

let node: roxmltree::Node = d.root_element();

Node が Element なのか何なのか確認する

match node.node_type()
{
  roxmltree::NodeType::Element => println!("This Node is an Element."),
  _ => println!("This Node is NOT an Element.")
}

または

let is_element: bool = node.is_element();
let is_comment: bool = node.is_comment();

Element な Node のタグ名を確認または取得する

// <xxx> か判定
let is_xxx_tag: bool = node.has_tag_name("xxx");

// タグ名を取得
let tag_name: roxmltree::ExpandedName = node.tag_name();

// タグ名のローカル名部分を取得; <abbrns:localpart> の localpart の部分
let tag_local_name: &str = tag_name.name();

// タグ名の名前空間部分を取得; <abbrns:localpart> の abbrns の部分の xmlns: 定義の uri 値
let tag_namespace: &str = tag_name.namespace();

XML Namespace 群を確認する

for ns: &roxmltree::Namespace in document.root_element().namespace()
{
  println!("name={:?} uri={}", ns.name(), ns.uri());
}

Node の Attribute 群を取得する

for attribute: &roxmltree::Attribute in node.attributes()
{
  println!("name={} value={}", attribute.name(), attribute.value());
}

Node の直近の下位(子) Element な Node 群を取得、または同位(姉妹)の Node 群を取得など

// 手法 A; .children から Element を .filter
let child_elements = document.root_element().children().filter(|n|n.node_type()==roxmltree::NodeType::Element);
for node: roxmltree::Node in child_elements
{
  println!("name={} text={:?}", node.tag_name().name(), node.text() );
}
// 手法 B; .first_element_child から Option を while して .next_sibling_element
let mut node_maybe = document.root_element().first_element_child();
while let Some(node) = node_maybe
{
  println!("name={} text={:?}", node.tag_name().name(), node.text() );
  node_maybe = node.next_sibling_element();
}

Node の上位(先祖)群、直近の上位(親)、下位(子孫)群

// 上位群
let ancentors: AxisIter = node.ancestors();
for node: roxmltree::Node in ancentors
{
  println!("ancentor name={} text={:?}", node.tag_name().name(), node.text() );
}

// 直近の上位
let parent_maybe: Option<roxmltree::Node> = node.parent_element();
let node: roxmltree::Node = parent_maybe.unwrap();
println!("parent name={} text={:?}", node.tag_name().name(), node.text() );

// 下位群
let descendants: Descendants = node.descendants();
for node: roxmltree::Node in descendants
{
  println!("descendant name={} text={:?}", node.tag_name().name(), node.text() );
}