Monday, August 17, 2009 / 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

以上です。