- PR -

XSLT/XPathについての質問

1
投稿者投稿内容
ずのみ
会議室デビュー日: 2002/03/01
投稿数: 3
投稿日時: 2002-03-01 12:59
初めてお便りします。
会議室というものに初めて参加するので、無礼なところがありましたらご指摘願います。

さて、早速ですが、XSLT/XPathについて3つほど質問させてください。

質問@
XSLT/XPathで、テキストノードに含まれる特定の文字列を要素に変換することができますか?

例えば、
<div>ああああXMLあああXMLああ</div>を
<div>ああああ<span>XML</span>あああ<span>XML</span>ああ</div>
のような形にしたいのですが...。

ノード内に変換対象がひとつだけなら、
contain()とsubstring-after()/before()の組み合わせでできそうですが、
対象が複数ある場合はどうすればよいのでしょうか。


A なぜtranslate()は変換元・先の文字列長が同じものしか変換してくれないのでしょうか?

B そもそもテキストノードの中身を加工するというのは、XSLTの思想に反するのですか?

では、よろしく回答願います。

以上
MMX
ぬし
会議室デビュー日: 2001/10/26
投稿数: 861
投稿日時: 2002-03-01 14:21
A なぜtranslate()は変換元・先の文字列長が同じものしか変換してくれないのでしょうか?
「文字列置換」でなく「文字置換」だから。a→x,b→y を "ab","xy" と指定

B そもそもテキストノードの中身を加工するというのは、XSLTの思想に反するのですか?
XSLT仕様の前書きにその様に書かれています。(初期想定は、目次・索引が作れればOK)
しかし、XSLTは最初に人々の前に出現した XMLのスクリプトで、標準にもなったので
限界を試すかのように使われることも多いです。クエリーにも使える(問い合わせ、更新)

しかし、無理はいけません、アルゴリズムを導入して効率を追求すると
XSLT の読みやすさが台なしになります。(最初からDOMで書くの以上に変になる)
(大昔 Prolog でも同様の現象が起きました)

XPath は大変便利で テキスト対正規表現操作(gオプション付) に XML構造対XPath操作
にあたります。text()ノードの中の操作は拡張関数やスクリプト呼び出しの
分担では(そうしないとXSLTの汎用肥大化になるでしょう)

[ メッセージ編集済み 編集者: MMX 編集日時 2002-03-09 12:04 ]
ずのみ
会議室デビュー日: 2002/03/01
投稿数: 3
投稿日時: 2002-03-01 16:27
早速のご回答ありがとうございます。

確かに、テキスト処理の拡充は仕様の肥大化につながりますね。

自分としては、なにもかもXSLT/XPathで一発で変換してしまいたかったのですが、
ここは一段かましてPerlなどで加工すると言うことでしょうか。
(@はできないということですよね?)

でもtranslate()の文字置換というのは文字列置換よりも需要が
あるのでしょうか?それとも文字置換しかできないような制限が
何かあるのですか?



MMX
ぬし
会議室デビュー日: 2001/10/26
投稿数: 861
投稿日時: 2002-03-01 17:13
--ここは一段かましてPerlなどで加工すると言うことでしょうか。
現在はそうと、思います。 XSLT/XPath に 「正規表現pattern」を、
の声は強いのですが。

1.の課題は テキストからxml を起こす、という境界線のとこです
(xml世界の内側で動く XSLTの範囲か?)
DOM(2?3?) では Range 関係のメソッドなら簡単にできるでしょう。

たとえ、文字列置換ができても、ただちに更新された
テキストが部分再パースされて、XMLの構造が更新される
とはならないでしょう。
XSLTの出力結果は <span> ではなく & lt;span& gt;
が想定される動作。
XML的には文字列操作を自由にされると、グチャグチャに
なりやすいかも。

もしXML が &XML; と書かれていたなら, DTDを読めるソフトを使い
展開済みテキストを出力できます。 DTDにエンティティ宣言を付けて
XSLTで恒等変換とか (やってみないと、わかりませんが)、
SGMLのタグ・ノーマライズ&エンティティ展開のUTILソフトとかで。
エンティティは辞書を使う変換なので、直接ポイントの XInclude より
可変度が高い。

読みやすさや、処理速度に目をつむれば、できます。
---------------------------------------------------
<?xml version="1.0" encoding="Shift_JIS"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:param name="x">XML</xsl:param><!-- 内容は定数 -->
<xsl:param name="y"><span><xsl:value-of select="$x"/></span></xsl:param>

<xsl:template match="/">
<xsl:apply-templates select="*"/>
</xsl:template>
<!-- div 中には 要素が入っていないと仮定して -->
<xsl:template match="div">
<xsl:copy>
<xsl:call-template name="divspan"/>
</xsl:copy>
</xsl:template>

<xsl:template name="divspan">
<xsl:param select="string(.)" name="cdr"/>
<xsl:choose>
<xsl:when test="contains($cdr,$x)">
<xsl:value-of select="substring-before($cdr,$x)"/>
<xsl:copy-of select="$y"/>
<xsl:call-template name="divspan">
<xsl:with-param select="substring-after($cdr,$x)" name="cdr"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$cdr"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>

</xsl:stylesheet>
---------------------------------------------------
もう一つの書き方は、apply-templates を mode で状態分けして
matchを切り替える方法でしょう。要素混在の扱いはこちらが
やりやすいかも。

[ メッセージ編集済み 編集者: MMX 編集日時 2002-03-02 01:24 ]
ずのみ
会議室デビュー日: 2002/03/01
投稿数: 3
投稿日時: 2002-03-04 21:00
名前付きテンプレートにして再帰的に呼び出すという方法ですね。
これだとsubstring-after()で切り出した文字列を、
テキストの終りが来るまで次々に変換対象にできますね。
なるほど、ためになりました。早速試してみます。
混在要素や、変換対象の文字列が複数種類ある場合のテンプレート
についてもこれをもとにして考えてみます。
どうもありがとうございました。
1

スキルアップ/キャリアアップ(JOB@IT)