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 version="1.0" encoding="UTF-8" ?>
<book>
<chapter>
<title>hello world 1</title>
<sect1>
<title>hello world 2</title>
</sect1>
</chapter>
</book>
このXML文書から章タイトルだけを抜き出してみます。
<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>
<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
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
以上です。