Home About Contact
XML

XPath で指定した特定部分だけをXML文書から抜き出すスタイルシート

XML文書から XPath で指定した部分だけを抜き出したい。 XSLTではデフォルトの変換規則があるため、これが意外に難しかったのでメモ。
(デフォルト規則が分かっていれば難しいことはない。)

XPathで指定した部分を取り出したいだけならば、xpathコマンドを使えばOK.
Ubuntu などでは、apt-get install libxml-xpath-perl でインストールできます。
以下のように使えます。

$ cat sample.xml | xpath -q -e "/book/chapter/title/text()"

事前準備

XML変換するために xsltproc をインストールしておきます。 Ubuntu なら以下のコマンドでインストールできます。(たぶん)

sudo apt install xsltproc

XML文書 sample.xml

<?xml version="1.0" encoding="UTF-8" ?>
<book>
	<chapter>
        <title>hello world 1</title>
        <sect1>
            <title>hello world 2</title>
        </sect1>
	</chapter>
</book>

このXML文書から章タイトルだけを抜き出してみます。

スタイルシートその1 get-text-1.xsl

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >

	<xsl:template match="/book/chapter/title/text()" >
        <xsl:copy-of select="." />
	</xsl:template>

</xsl:stylesheet>

章タイトルだけを抜き出すスタイルシート→ これは実際にはうまくいかない

変換実行

xsltproc get-text-1.xsl sample.xml

結果

<?xml version="1.0" encoding="UTF-8"?>
      
	hello world 1
	      
            hello world 2

これは意図していない結果です。 hello world 1 だけを抜き出したいのですが、他の部分も出力されています。 調べてみると、XSLTではデフォルト規則として、以下のスタイルシートが暗黙に定義されているとのこと。

<xsl:template match="text()">
    <xsl:value-of select="." />
</xsl:template>

スタイルシートその2(改良版)

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >

	<xsl:template match="text()" />

	<xsl:template match="/book/chapter/title/text()" >
        <xsl:copy-of select="." />
	</xsl:template>

</xsl:stylesheet>

章タイトルだけを抜き出すスタイルシート、改良版。

この記述を追加することにより…

    <xsl:template match="text()" />

デフォルトのスタイルシートを上書きして、 テキストデータをそのまま出力するというデフォルト規則を無効にします。

結果

<?xml version="1.0" encoding="UTF-8"?>hello world 1

スタイルシートその3(完成)

xsl:output を追加して、XML宣言 を出力しないようにします。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >

	<xsl:output method="text" encoding="UTF-8" />

	<xsl:template match="text()" />

	<xsl:template match="/book/chapter/title/text()" >
        <xsl:copy-of select="." />
	</xsl:template>

</xsl:stylesheet>

結果

hello world 1

以上です。