私は XML を使用して小さな連絡先リストを保存しており、それを CSV ファイルに変換する XSL テンプレートを作成しようとしています。問題は出力内の空白です。
出力:
Friend, John, Smith, Home,
123 test,
Sebastopol,
California,
12345,
Home 1-800-123-4567, Personal [email protected]
読みやすく開発しやすいように、ソース XML ファイルと関連する XSL テンプレートの両方にインデント/スペースを入れましたが、余分な空白がすべて出力に含まれてしまいます。XML 自体にはノード内に余分な空白はなく、書式設定のためにノードの外側にのみあります。XSLT についても同様です。
CSV ファイルを有効にするには、各エントリが分割されずに独自の行にある必要があります。XML と XSLT から余分な空白をすべて削除する (1 行の長いコードにする) 以外に、出力の空白を取り除く別の方法はありますか?
編集: ここに小さな XML サンプルがあります:
<PHONEBOOK>
<LISTING>
<FIRST>John</FIRST>
<LAST>Smith</LAST>
<ADDRESS TYPE="Home">
<STREET>123 test</STREET>
<CITY>Sebastopol</CITY>
<STATE>California</STATE>
<ZIP>12345</ZIP>
</ADDRESS>
<PHONE>1-800-123-4567</PHONE>
<EMAIL>[email protected]</EMAIL>
<RELATION>Friend</RELATION>
</LISTING>
</PHONEBOOK>
XSLT は次のとおりです。
<?xml version="1.0" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" />
<xsl:template match="/">
<xsl:for-each select="//LISTING">
<xsl:value-of select="RELATION" /><xsl:text>, </xsl:text>
<xsl:value-of select="FIRST" /><xsl:text>, </xsl:text>
<xsl:value-of select="LAST" /><xsl:text>, </xsl:text>
<xsl:if test="ADDRESS">
<xsl:for-each select="ADDRESS">
<xsl:choose>
<xsl:when test="@TYPE">
<xsl:value-of select="@TYPE" />,
</xsl:when>
<xsl:otherwise>
<xsl:text>Home </xsl:text>
</xsl:otherwise>
</xsl:choose>
<xsl:value-of select="STREET" />,
<xsl:value-of select="CITY" />,
<xsl:value-of select="STATE" />,
<xsl:value-of select="ZIP" />,
</xsl:for-each>
</xsl:if>
<xsl:for-each select="PHONE">
<xsl:choose>
<xsl:when test="@TYPE">
<xsl:value-of select="@TYPE" />
</xsl:when>
<xsl:otherwise><xsl:text>Home </xsl:text></xsl:otherwise>
</xsl:choose>
<xsl:value-of select="." /><xsl:text >, </xsl:text>
</xsl:for-each>
<xsl:if test="EMAIL">
<xsl:for-each select="EMAIL">
<xsl:choose>
<xsl:when test="@TYPE">
<xsl:value-of select="@TYPE" /><xsl:text > </xsl:text>
</xsl:when>
<xsl:otherwise><xsl:text >Personal </xsl:text></xsl:otherwise>
</xsl:choose>
<xsl:value-of select="." /><xsl:text >, </xsl:text>
</xsl:for-each>
</xsl:if>
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
ベストアンサー1
XSLT では、空白は関連データである可能性が高いため、デフォルトで保持されます。
出力に不要な空白が入らないようにする最善の方法は、そもそも空白を作成しないことです。次のことはしないでください。
<xsl:template match="foo">
foo
</xsl:template>
なぜなら、それは"\n··foo\n"
プロセッサの観点からは、
<xsl:template match="foo">
<xsl:text>foo</xsl:text>
</xsl:template>
スタイルシート内の空白は、XML 要素間にのみ存在する限り無視されます。簡単に言うと、XSLT コードのどこにも「裸の」テキストを使用せず、常に要素内に囲みます。
また、非特定的な表現を使うと、
<xsl:apply-templates />
テキスト ノードのデフォルトの XSLT ルールでは「出力にコピーする」とされているため、これは問題となります。これは「空白のみの」ノードにも適用されます。たとえば、次のようになります。
<xml>
<data> value </data>
</xml>
3 つのテキスト ノードが含まれます。
"\n··"
(直後の<xml>
)"·value·"
- "
\n"
(直前</xml>
)
出力に #1 と #3 が紛れ込むのを回避するには (不要なスペースが発生する最も一般的な原因)、空のテンプレートを宣言してテキスト ノードのデフォルト ルールをオーバーライドします。
<xsl:template match="text()" />
すべてのテキスト ノードがミュートされ、テキスト出力を明示的に作成する必要があります。
<xsl:value-of select="data" />
値から空白を削除するには、normalize-space()
XSLT 関数を使用できます。
<xsl:value-of select="normalize-space(data)" />
ただし、関数は文字列内にある空白を正規化するため、たとえば のよう"·value··1·"
になるので注意してください"value·1"
。
さらに、<xsl:strip-space>
および<xsl:preserve-space>
要素を使用することもできますが、通常これは必要ありません (個人的には、上記のように明示的な空白処理を好みます)。