質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.77%

  • XPath(XML Path)

    70questions

    XML Path Language (XPath; XMLパス言語)は、マークアップ言語 XML に準拠した文書の特定の部分を指定する言語構文の事をいいます。XPathはXMLとは別の構文を使用します。XMLドキュメントの抽象、論理ストラクチャ上で動作します。

  • XSLT

    9questions

    XSLTは、組み立てられた文書を(XML、HTML、そしてプレーンテキストのような)別のフォーマットに変化する為にデザインされたXMLの為の変換用言語です。

xmlデータの検索と構造解析にxsltを使おうとしたのですが…

解決済

回答 1

投稿

  • 評価
  • クリップ 2
  • VIEW 365

KojiDoi

R総合1位

前提・実現したいこと

非常に複雑な構造をもったXMLファイルから必要なデータを抜き出して利用したいと思っています。
しかし、データ構造などに関する充分な資料がなく、目当てのデータがどこに含まれているかを調べるところから始めなければなりません。
目当てのキーワードは複数の異なる文脈で使用されていることがわかっています。したがって、単にそのキーワードについて検索するだけではなく、それがどのようなタグの下に書かれているかも把握しなければなりません。これをxsltとxpathを利用して簡素に実現できないかと考えました。

発生している問題

そこで、後述のように、xsltファイルを作ってみたのですが実行結果は微妙に期待とずれております。その原因と対策をお教えいただければ嬉しく思います。xsltなんか使わなくてもこうすれば簡単だよ!的なアドバイスも大歓迎です。

該当のソースコードとデータ

テストデータ(test.xml)

<?xml version="1.0" encoding="UTF-8"?>
<xml>
<node1 id="node1_1">
  <node2 id="node2_1">
   abcd
  </node2>
  <node2 id="node2_2">
    <node3 id="node3_1">
      xxxx
    </node3>
  </node2>
</node1>
<node1 id="node1_2">
  <node2 id="node2_3">
    cccc
    <node3 id="node3_2">
      xxxx
    </node3>
  </node2>
</node1>
</xml>

某サイトの記事を参考に、"xxxx"という文字列を含むノードをリストアップすべく見よう見まねで書いてみたxsltデータ(test.xsl)

<?xml version="1.0" encoding="utf-8"?>
<!-- https://stackoverflow.com/questions/12369734/get-all-ancestors-of-current-node -->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <xsl:variable name="curr" select="//*[contains(text(),'xxxx')]"></xsl:variable>
        <xsl:variable name="test1" select="$curr/self::*"></xsl:variable>
        <xsl:for-each select="$test1">
start
          <xsl:value-of select="concat(name(), ': ID=', @id)"></xsl:value-of>
          <xsl:variable name="test2" select="$test1/ancestor::*"></xsl:variable>
          <xsl:for-each select="$test2">
 ancestor
            <xsl:value-of select="concat(name(), ': ancestorID=', @id)"></xsl:value-of>
          </xsl:for-each>
end
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

試したこと

次のようにコマンドを実行してみました。

xsltproc ~/work/test.xsl ~/work/test.xml


すると、次のような結果が得られます。

<?xml version="1.0"?>

start
          node3: ID=node3_1
 ancestor
            xml: ancestorID=
 ancestor
            node1: ancestorID=node1_1
 ancestor
            node2: ancestorID=node2_2
 ancestor
            node1: ancestorID=node1_2
 ancestor
            node2: ancestorID=node2_3
end

start
          node3: ID=node3_2
 ancestor
            xml: ancestorID=
 ancestor
            node1: ancestorID=node1_1
 ancestor
            node2: ancestorID=node2_2
 ancestor
            node1: ancestorID=node1_2
 ancestor
            node2: ancestorID=node2_3
end

惜しいところですが、余計な兄弟のデータが一生に出力されており、これでは使えません。私としては次のような出力を期待しているのです。

<?xml version="1.0"?>

start
          node3: ID=node3_1
 ancestor
            xml: ancestorID=
 ancestor
            node1: ancestorID=node1_1
 ancestor
            node2: ancestorID=node2_2
 end

start
          node3: ID=node3_2
 ancestor
            xml: ancestorID=
 ancestor
            node1: ancestorID=node1_2
 ancestor
            node2: ancestorID=node2_3
end

補足情報(言語/FW/ツール等のバージョンなど)

環境:CentOS 6.6

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

check解決した方法

+1

 自己解決!

進捗がありました。以下のxlstによって、所定のキーワードを含むノード+その上位ノードの表示が一応達成できました。

この結果を利用し、改めてxpath式を組み、perl+xml::xpathあたりを利用してデータ取得・二次利用を実現できそうです。

<?xml version="1.0" encoding="utf-8"?>
<!-- https://stackoverflow.com/questions/12369734/get-all-ancestors-of-current-node -->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <xsl:variable name="curr" select="//*[contains(text(),'xxxx')]"></xsl:variable>
        <xsl:variable name="test1" select="$curr/self::*"></xsl:variable>
        <xsl:for-each select="$test1">
found item
          <xsl:value-of select="concat('node=', name(), ' ID=', @id)"></xsl:value-of>
          <xsl:variable name="test2" select="./ancestor::*"></xsl:variable>
          <xsl:for-each select="$test2">
            <xsl:value-of select="concat(' ancestorNode=', name(), ' ancestorID=', @id)"></xsl:value-of>
          </xsl:for-each>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

質問文に示したバージョンからの重要な変更点は以下です。

<xsl:variable name="test2" select="./ancestor::*">


これで余計な兄弟ノードをたどることはなくなりました。

 データファイル

<xml>
<node1 id="node1_1">
  <node2 id="node2_1">
   abcd
  </node2>
  <node2 id="node2_2">
    <node3 id="node3_1">
      xxxx
    </node3>
  </node2>
</node1>
<node1 id="node1_2">
  <node2 id="node2_3">
    cccc
    <node3 id="node3_2">
      xxxx
    </node3>
  </node2>
</node1>
<node1 id="node1_3">
xxxx
</node1>
</xml>

 実行結果

$ xsltproc_lite test.xsl test.xml /dev/stdout                                                                                             [ ~/work ] 
<?xml version="1.0"?>

found item
          node=node3 ID=node3_1 ancestorNode=xml ancestorID= ancestorNode=node1 ancestorID=node1_1 ancestorNode=node2 ancestorID=node2_2
found item
          node=node3 ID=node3_2 ancestorNode=xml ancestorID= ancestorNode=node1 ancestorID=node1_2 ancestorNode=node2 ancestorID=node2_3
found item
          node=node1 ID=node1_3 ancestorNode=xml ancestorID=

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.77%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • XPath(XML Path)

    70questions

    XML Path Language (XPath; XMLパス言語)は、マークアップ言語 XML に準拠した文書の特定の部分を指定する言語構文の事をいいます。XPathはXMLとは別の構文を使用します。XMLドキュメントの抽象、論理ストラクチャ上で動作します。

  • XSLT

    9questions

    XSLTは、組み立てられた文書を(XML、HTML、そしてプレーンテキストのような)別のフォーマットに変化する為にデザインされたXMLの為の変換用言語です。