- PR -

空白文字で区切られた要素から文字列を抜き出したい。

1
投稿者投稿内容
ADO15
会議室デビュー日: 2004/07/08
投稿数: 7
投稿日時: 2004-11-08 13:26
どなたか教えてください。

xmlの要素の中に空白文字で区切られたデータがあるとします。

<youbi>getsu ka sui moku kin do nichi</youbi>

この要素から、3番目の要素suiをxslで抜き出したいのですが、
方法が見つかりません。

要素に入る文字列の長さが決まっていれば、
substring 関数で9文字目から3文字抜き出すこともできますが、
要素の中に入るデータが多い場合を考えると使えません。

そもそも、それぞれを要素に区切るべきなのかも知れませんが・・・。

見たことがありませんが、格子点データなどをxml化した場合などは
同じような問題が発生すると思われます。

ご存知のかた、お願いいたします。
MMX
ぬし
会議室デビュー日: 2001/10/26
投稿数: 861
投稿日時: 2004-11-08 13:40
XML 関連のAPI には 「サブパーサー」のようなものはありません。
文字列全体を取り出し、伝統的なテキスト処理を行います。

それが、正規表現での切り出しとか tokenize のように軽いものか
各種パーサージェネレータを使うようなものになるかは、文法しだい。

SGMLパーサーなら データタグとか言って 文字列パターンをタグ扱い
することができます。(日本語文書はまず見つからない)
例 O'Reilly Book Hacking XML Hack #94,
http://www.xml.com/lpt/a/2004/09/15/XMLHacks.html
本の紹介ページから、サンプルで使ったソースダウンロード
へのリンクが探せます。OpenSP1.5 でも動きました。

>格子点データなどをxml化した場合などは
同じような問題が発生すると思われます。
Bio の遺伝子情報の交換では バイナリの ASN.1 を使う場合もあります。

使用予定のモジュールで、XPath2.0 の関数
が先行実装されていないか、確認してみましょう
http://www.w3.org/TR/xquery-operators/#regex-syntax

[ メッセージ編集済み 編集者: MMX 編集日時 2004-11-08 14:58 ]
バクシ
会議室デビュー日: 2004/10/06
投稿数: 12
投稿日時: 2004-11-10 11:47
tokenize あるいは split に類する操作は,再帰テンプレートで実現します。あちこちのFAQに実例があるでしょう。
tokenのX番目を取り出すには,
手順1 tokenizeの結果を変数にセットする
手順2 その変数のノードセットとして扱い,X番目の子要素を取り出す。

注意するのは,変数をノードセットとして操作する方法が,XSLTエンジンによって異なることです。
saxonはxsl version1.1に準拠していますから, "$変数名"でノードセットとして扱えます。
MSXMLは,拡張関数node-set($変数名)を使って,ノードセットに変換します。
XALANは,どうだったか,忘れてしまいました。ごめんなさい。

XMLが下の形だとすると
<root>
<youbi>getsu ka sui moku kin do nichi</youbi>
</root>

3番目を取り出すスタイルシートはこのとおり。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
<xsl:variable name="data-set">
<xsl:apply-templates/>
</xsl:variable>
<data>
<xsl:value-of select="$data-set/*[3]"/>
</data>
</xsl:template>

<xsl:template match="youbi">
<xsl:call-template name="tokenize">
<xsl:with-param name="str" select="normalize-space(.)"/>
</xsl:call-template>
</xsl:template>

<xsl:template name="tokenize">
<xsl:param name="str"/>
<xsl:choose>
<xsl:when test="contains($str, ' ')">
<token>
<xsl:value-of select="substring-before($str, ' ')"/>
</token>
<xsl:call-template name="tokenize">
<xsl:with-param name="str" select="substring-after($str, ' ')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<token><xsl:value-of select="$str"/></token>
</xsl:otherwise>
</xsl:choose>
</xsl:template>

</xsl:stylesheet>



[ メッセージ編集済み 編集者: バクシ 編集日時 2004-11-10 11:52 ]
TAKABE
常連さん
会議室デビュー日: 2003/05/14
投稿数: 43
投稿日時: 2004-11-10 14:57
 XSLT1.0において、仕様外の拡張関数などは使わずに、3番目だけを取り出すスタイルシートは以下のとおりです。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:variable name="junban" select="3" />
<xsl:variable name="kugiri" select="' '" />

<xsl:template match="youbi">
<xsl:call-template name="takeout">
<xsl:with-param name="str" select="normalize-space(.)"/>
<xsl:with-param name="num" select="$junban"/>
</xsl:call-template>
</xsl:template>

<xsl:template name="takeout">
<xsl:param name="str"/>
<xsl:param name="num"/>
<xsl:variable name="num1" select="$num - 1"/>
<xsl:variable name="car" select="substring-before($str, $kugiri)"/>
<xsl:variable name="cdr" select="substring-after($str, $kugiri)"/>
<xsl:choose>
<xsl:when test="$num1 = 0">
<xsl:value-of select="$car" />
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="takeout">
<xsl:with-param name="str" select="$cdr"/>
<xsl:with-param name="num" select="$num1"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>

</xsl:stylesheet>
バクシ
会議室デビュー日: 2004/10/06
投稿数: 12
投稿日時: 2004-11-11 08:57
XSLT2.0 XPath2.0 を実装した saxon7(http://www.saxonica.com)を使えば、

tokenize()関数を使って
<xsl:value-of select="tokenize(normalize-space(//youbi), ' ')[3]"/>
で、"sui"を取り出せます。あっけないこと、今まで再帰テンプレートを使って頭をひねっていたのが馬鹿馬鹿しくなります。tokenize()関数の二つ目の引き数には,正規表現が使えます。

tokenize()関数の結果は、<xsl:for-each>で操作することも可能。
<xsl:for-each select="tokenize(normalize-space(//youbi), ' ')">
<xsl:if test="position()=3">
<xsl:value-of select="."/>
</xsl:if>
</xsl:for-each>
は、上の<xsl:value-of>要素と同じ結果になります。
TAKABE
常連さん
会議室デビュー日: 2003/05/14
投稿数: 43
投稿日時: 2004-11-13 12:44
 バクシ様、こんにちは。
>XALANは,どうだったか,忘れてしまいました。ごめんなさい。
 私も興味を持って調べてみました。
http://www.xml.com/pub/a/2003/07/16/nodeset.html#tab.namespaces
 を見てみたら、ほとんどのメジャーな実装で大丈夫のようですね。
 私は今までMSXMLで使えることを知らずに苦労していたので、これはありがたいです。
 まあ何にせよ、XSLT 2.0が待ち遠しいというところです。
ADO15
会議室デビュー日: 2004/07/08
投稿数: 7
投稿日時: 2004-11-22 23:04
皆様、詳しい返答ありがとうございました。
まだ勉強中な為、十分な理解をするのに時間がかかっており、
お礼の言葉が遅くなったことをお詫びいたします。

今回の例では、TAKABEさまの例がとても参考になりました。
というのは、
私の基本線は、多くの方に使っていただくスタイルシートを作ることにあるためです。
素人とまでは行きませんが、普通の人が手間なく使用できる環境が望ましい。
で、
xsltによる変換・出力には、さまざまなパーサー?エンジン?があり、
どれを使うかについても、
xsltのバージョンについても
一番広くなじまれている方法を取りたいと考えています。

xmlを変換する上で、どの方法が効果的かどうか、さらに勉強したいと思っています。

MMXさま バクシさま のアドバイスも大変参考になりました。
今やってみたいスタイルシートには、さらに疑問点がありますが、
内容が異なるので、別スレッドで質問することとします。

皆様 ありがとうございました。 
1

スキルアップ/キャリアアップ(JOB@IT)