XMLとxPathを使って特定要素のテキストを表示する方法について

このQ&Aのポイント
  • xml,xslを勉強している中で、xPathの指定がうまくできない状態です。特定の要素のテキストを表示する方法を教えてください。
  • 具体的には、XMLのartistのテキストノードが特定の文字列に一致する場合、その要素のtitleを表示したいです。
  • 既存のxPathでは、一致する要素だけでなく部分一致も選択してしまっています。正確な一致のみを選択するxPathの定義方法を教えてください。
回答を見る
  • ベストアンサー

テキストノードの文字列に一致した要素の取得(xPath

xml,xslを勉強しているのですが、xPathの指定が上手く定義できない状態です。ご教授の程お願い致します。 下記がxml,xslです <!-- アーティスト名とタイトルを明記したxml --> -- music.xml <?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet type="text/xsl" href="music.xsl"?> <music> <artist> Ciel <title>wake</title> </artist> <artist> Flew <title>BANG</title> </artist> <artist> cobu                 // (1) <title>calling</title> </artist> <artist> cobukure <title>dammy</title> </artist> </music> <!-- 条件に一致したアーティスト名、タイトルを表示するxsl --> -- music.xsl <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <html> <head><title></title></head> <body> <xsl:for-each select = "descendant::artist[contains(text(),'cobu')]"> // (2) <xsl:value-of select ="text()" />: <xsl:value-of select ="title" /><br/> </xsl:for-each> </body> </html> </xsl:template> </xsl:stylesheet> //上記の処理結果 cobu :calling cobukure :dammy //希望する処理結果 cobu :calling ・質問内容 XMLのartistのテキストノード=cobuをxsl:for-eachでselectして、 titleのcallingを表示したい 本、サイトなどで調べて、 descendant::artist[contains(text(),'cobu')]のxPathまでは、 導けたのですが、この場合は、cobuを含むので、 artistのテキストノード=cobukureもselectされdummyが表示されてしまいます。 処理結果、 cobu :callingのみselectできるxPathの定義をご教授の程お願い致します

  • XML
  • 回答数2
  • ありがとう数7

質問者が選んだベストアンサー

  • ベストアンサー
  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.1

選ばれた要素の空白を除いた長さが4であるかをチェックしてみてはいかがでしょう <xsl:for-each select = "descendant::artist[contains(text(),'cobu')]">   <xsl:if test="string-length( normalize-space( text() ) ) = 4" >     <xsl:value-of select ="text()" />:     <xsl:value-of select ="title" /><br/>   </xsl:if> </xsl:for-each> といった具合で ...

ques9999
質問者

お礼

回答、教授して頂きありがとうございます。 ご指摘の方法で、下記の用に定義したところ、データを取得できました。 <xsl:for-each select = "descendant::artist[contains(text(),'cobu') and (string-length( normalize-space( text() ) ) = string-length('cobu'))]"> 上記以外の方法で、xPath指定できないか、考えたいと思います。 ありがとうございました。

ques9999
質問者

補足

自己解決だと思うのですが、下記のように明記したらデータを 取得することができました。 *Mac FireFox3.5.2でのみの確認となりますが... <xsl:for-each select = "descendant::artist[normalize-space(text())='cobu']"> 他の方法で、定義する方法がありましたら、ご教授願います。

その他の回答 (1)

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.2

<xsl:for-each select = "descendant::artist[normalize-space(text())='cobu']"> で IE6でも表示しましたよ

ques9999
質問者

お礼

検証して頂きありがとうございます。 normalize-spaceを意識していなかったので、 <xsl:for-each select = "descendant::artist[text()='cobu']"> と定義した場合、データをひっぱってくることができておりませんでした。 また、ひとつ勉強させて頂きました。 ご丁寧な返答ありがとうございました。

関連するQ&A

  • xpath でn番目のテキストノード取得

    xpathで//text()とするとすべてのテキストノードが取得できますが、 この中からn番目のテキストノードを取得することは可能でしょうか? (プログラムでループではなく、xpathで。) <?xml version='1.0'?> <root><foo>aaa</foo><bar>bbb</bar><buz>bbb</buz></root> //text()[1]でaaaがとれるかと思ったんですが。。。 よろしくお願いします。

    • ベストアンサー
    • XML
  • XML::XPath -- 追加したノードが見付からない

    XMLのテンプレートを既存のXMLに追加したのですが、 その後 findnodes() で検索しても合致しません。 XML::XPath::Node::Element->new() を使って作成したものは 合致してくれます。 XML::XPath::XMLParser でパースしたものを追加して findnodes() で合致させるにはどのようにしたらよいのでしょうか。 ------------------------------- use XML::XPath; #### 元のXML my $xmldata = <<EOM; <?xml version="1.0" encoding="UTF-8" ?> <list>   <item>orange</item>   <item>apple</item>   <item>lemon</item> </list> EOM ### 追加するXMLのテンプレート my $xmlappend = <<EOM;   <item>pine</item> EOM ## 追加先ノードを取り出す my $xml = XML::XPath->new( xml=>$xmldata ); my ($list) = $xml->findnodes('/list'); ## 追加用XMLを作成して追加 my $append = XML::XPath::XMLParser->new( xml=>$xmlappend )->parse; $list->appendChild( $append ); ## もういっこ追加。こちらはこの場で作る $newnode = XML::XPath::Node::Element->new('item'); $newtext = XML::XPath::Node::Text->new('banana'); $newnode->appendChild( $newtext ); $list->appendChild( $newnode ); ## 現状確認 → pine は入っていた print $list->toString."\n"; ## item一覧を取得 @nodes = $xml->findnodes('/list/item'); ## 一覧を出力 → 追加した pine が出力されない。 bananaはある。 map{ print $_->toString."\n" } @nodes;

    • ベストアンサー
    • Perl
  • ある文字列を含むノードが存在するかを判定したい

    お世話になります。 次のようなXMLファイルがあります。 <root> <data> <code>1</code> <value>aiueo</value> </data> <data> <code>2</code> <value>kakikukeko</value> </data> <data> <code>3</code> <value>aiueo</value> </data> </root> 「aiueo」が一つでも含まれている<value>ノードが存在するならば、という判定をXSLファイルの中で行いたいです。 contains関数を使うのかなと思っているのですが、ルートノードから見て孫のノードを繰り返し探す処理が分からず困っています。 プログラムの前後の処理の都合上、ルートからの絶対パスで辿りたいのですが、方法を教えて下さいますでしょうか。 宜しくお願いします。

    • ベストアンサー
    • XML
  • XSLでノードの順番取得

    XSLでノードの順番の取得は可能でしょうか? 例えば、 <data> <title>xxxxxx</title> <item>xxxxxx</item> </data> のようなXMLで、<data>タグの一番最初の要素は、<title>タグというのは 調べられます? よろしくお願いします。

    • ベストアンサー
    • XML
  • for-eachが上手くいきません

    xslを使ってごくごく基本的なことをしようとしているのですが、何故か上手くいかず煮詰まっています。 ここが違う!というツッコミを是非よろしくお願いします。 ごく単純なことですが、xmlで複数の<site></site>内にあるデータそれぞれ表示させるためxslファイル内でfor-eachを使っています。for-each抜きだと一つ目の<site></site>がちゃんと表示されるのですが、for-eachを付け加えた途端何も表示されなくなってしまいます。 参考書を見て何度確認、やり直しをしても上手くいかず困っています。 使っているコードは以下の通りです。 XMLファイル: <?xml version="1.0" encoding="Shift-JIS" ?> <?xml-stylesheet type="text/xsl" href="links.xsl" ?> <links> <site> <name>サイト1</name> <banner>some.jpg</banner> </site> <site> <name>サイト2</name> <banner>other.jpg</banner> </site> </links> XSLファイル: <?xml version="1.0" encoding="Shift-JIS" ?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <html> <head><title><title></head> <body> <table border="1"> <xsl:for-each select="links/site"> <tr> <td> <img> <xsl:attribute name="src"> <xsl:value-of select="links/site/banner" /> </xsl:attribute> </img> <b><xsl:value-of select="links/site/name" /></b> </td> </tr> </xsl:for-each> </table> </body> </html> </xsl:template> </xsl:stylesheet> 何かアドバイスがありましたらお聞かせ下さい。

    • ベストアンサー
    • XML
  • XSLTでの複数のXML検索結果を統合するには?

    初歩的な質問でごめんなさい。 XSLTを使って複数のXMLを検索した結果を、表示したいのですが、結果を1つのテーブルに統合するにはどうすればいいのでしょう。 次のスクリプトを基に作りたいのですが。 function search (keyword) { node = thexsl.XMLDocument.selectSingleNode("//xsl:for-each"); if(keyword) node.setAttribute("select", "//data[contains(word, '" + keyword + "')]"); else node.setAttribute("select", "//data"); str = thexml.XMLDocument.transformNode(thexsl.XMLDocument); view1.innerHTML = str; } 次のファイルを利用して検索したいです、 <xml id="thexml1" src="db1.xml"></xml> <xml id="thexml2" src="db2.xml"></xml> <xml id="thexml3" src="db3.xml"></xml> <xml id="thexsl" src="db.xsl"></xml> xmlファイルの内容 <?xml version="1.0" encoding="utf-8" ?> <dataroot xml:lang="ja"> <data>・・・</data>  ・・・ </dataroot> xslファイルの内容 <?xml version="1.0" encoding="utf-8" ?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:template match="/"> <table> <tr>・・・</tr> <xsl:for-each select="//data"> <tr>・・・</tr> </xsl:for-each> </table> </xsl:template> </xsl:stylesheet> よろしくお願いします。

    • 締切済み
    • XML
  • XSLTで、あるノードの Text を別なノードの Name として参照

     変換したいXML文書の最初のトップレベルノードの階層をたどって text を拾っていくと、その text に一致する name のノードが次のトップレベルノードの階層で、出現するようになっています。  そこで、まず、最初のノードの階層をたどっていって、その順序で、2番目のノードから値を引いてきて表示させたいのです。 ■変換したい XML 文書 DataDocument.xml <datadocument> <setteischema> <sitem>solution <scategory>solution1</scategory> </sitem> <sitem>itsales <scategory>itsales1</scategory> </sitem> </setteischema> <setteivalue> <solution> <solution1>ソリューション1</solution1> </solution> <itsales> <itsales1>ITセールス1</itsales1> </itsales> </setteivalue> </datadocument> それに対して、適用したい XSL は次のようなものです。 ■変換命令を記述したXSL文書 StyleDocument.xsl <xsl:template match="setteischema" > <xsl:for-each select="*"> <xsl:variable name="foo" select="text()"/> <xsl:for-each select="*"> <xsl:variable name="bar" select="text()"/> <xsl:value-of select="★1" /> </xsl:for-each> </xsl:for-each> </xsl:template> 実際は★1の部分で setteivalue/$foo/$var といったパスで得られるノードのテキストを表示させたいのです。 どうしたらできますか? よろしくお願いします。

    • ベストアンサー
    • XML
  • XPathGraphでノードの値を取得できない

    IT戦記経由で知った http://d.hatena.ne.jp/amachang/20080425/1209098271 XPathGraph http://xpath.kayac.com/ なるサービスがあります。 テストのために, Windows Live SkyDriveにアップロードした http://qfrfbw.bay.livefilestore.com/y1pR1j83PrREpBohBHZsCgD8GDU8FdFa4EArE7o6flrxaCyM3pSbtxD69QyPvue3X2p2-97-V9oNadelUXUfaHXaA/20080430-2.xml のtest要素のテキストノードを数値として扱った時の値55を取得しようと URLを打ち込み XPathを number(/test/text()) としたのですが, 値が取得できませんでした とされてしまいました。 何か条件が足りないのでしょうか?

    • 締切済み
    • XML
  • ファイルサーバの日本語フォルダ名へのリンク

    勉強しはじめで質問内容にも至らない点があるかと思いますが何卒アドバイスをお願いいたします。 イントラを作成するにあたり、ファイルサーバー上の日本語名フォルダにリンクしたいのですが、文字化けをしてしまいます。ソースは下記のような感じです。 ■xmlファイル「test.xml」 <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <root> <item> <title>日本語フォルダ名</title> <link>\\test01¥テストデータ</link> </item> <item> <title>管理</title> <link>\\test01\経費管理</link> </item> </root> ■xslファイル「test.xsl」 <?xml version="1.0" encoding="utf-8"?><!-- DWXMLSource="test.xml" --> <!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp " ">  中略 <!ENTITY euro "?"> ]> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html" encoding="utf-8"/> <xsl:template match="/"> <xsl:for-each select="root/item"> <a href="{link}"><xsl:value-of select="title"/></a><br /><br /> </xsl:for-each> </xsl:template> </xsl:stylesheet> これをオーサリングソフト(Dreamweaver8を使用)でプレビューすると、日本語フォルダ名が文字化けをしてしまいリンクができません。 ファイル名を半角英数にすれば済む話ではあるのですがあまりに大量のファイルがあるのと、管理上の問題でフォルダ名はなんとか日本語のままで使用したく考えております。 お手数ですが回避策、代替案などございましたら教えていただけると助かりますので何卒よろしくお願い申し上げます。

    • ベストアンサー
    • XML
  • xsl、xpath式の書き方について

    xslで質問させてください。 以下のようなxmlとxslを作っているのですが、xslの最後のほうで、 sample.xmlの/empList/emp/type/@idの値に応じて、typeList.xmlの/typeList/type/titleの値を取得したくて、 xsl:value-of select="document('typeList.xml')/typeList/type[@id = type/@id]/title/text()" /> と書いていますが、うまくいきません。どうすればいいでしょうか? -----[sample.xml] <?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet href="a.xsl" type="text/xsl"?> <empList> <emp> <type id="1" /> <name>鈴木</name> <desc>あああ</desc> </emp> <emp> <type id="2" /> <name>田中</name> <desc>いいい</desc> </emp> </empList> -----[typeList.xml] <?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet href="a.xsl" type="text/xsl"?> <typeList> <type id="1"> <title>タイプ1</title> </type> <type id="2"> <title>タイプ2</title> </type> </typeList> -----[a.xsl] <?xml version="1.0" encoding="UTF-8" ?> <xsl:stylesheet version="1.0" xmlns="http://www.w3.org/1999/xhtml" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html" encoding="UTF-8" omit-xml-declaration="yes" doctype-public="-//W3C//DTD XHTML 1.1//EN" doctype-system="http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" media-type="text/html" /> <xsl:template match="/"> <html> <head><title>サンプル</title></head> <body> <xsl:apply-templates select="empList/emp" /> </body> </html> </xsl:template> <xsl:template match="emp"> <h2><xsl:value-of select="name/text()" /></h2> <p>タイプ:<xsl:value-of select="document('typeList.xml')/typeList/type[@id = type/@id]/title/text()" /></p> <p>メモ:<xsl:value-of select="desc/text()" /></p> </xsl:template> </xsl:stylesheet>

    • ベストアンサー
    • XML

専門家に質問してみよう