質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
XSLT

XSLTは、組み立てられた文書を(XML、HTML、そしてプレーンテキストのような)別のフォーマットに変化する為にデザインされたXMLの為の変換用言語です。

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

Q&A

解決済

1回答

2186閲覧

XSLTのdocument()関数を利用して、外部リストに応じた文字置換をする

UG_ito_Pcorp

総合スコア13

XSLT

XSLTは、組み立てられた文書を(XML、HTML、そしてプレーンテキストのような)別のフォーマットに変化する為にデザインされたXMLの為の変換用言語です。

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

0グッド

0クリップ

投稿2020/04/13 07:19

編集2020/04/13 08:52

XSLT:外部ファイルの内容(リスト)に応じた文字置換

XSLTで、document()関数を使用して外部ファイルへアクセスし、外部ファイルのリストに応じた文字置換が行いたいです。

変換元ファイル:test.xml

<topic> <title>吾輩は猫である。</title> <body> <section> <title>一</title> <p>吾輩は猫である。</p> <p>名前はまだ無い。</p> <p>どこで生れたかとんと見当がつかぬ。</p> <p>何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。</p> <p>吾輩はここで始めて人間というものを見た。</p> </section> </body> </topic>

試したこと

外部ファイルにアクセスせず、ひとつの単語の置換には、下記のXSLTを使用しました。

XSLT:change.xsl

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> 《中略》 <xsl:template match="p"> <xsl:variable name="target_tarm" select="'吾輩'"/> <xsl:variable name="replace_tarm" select="'【わたくし】'"/> <xsl:choose> <xsl:when test="contains(./text(),$target_tarm)"> <xsl:variable name="non_change_before"> <xsl:value-of select="substring-before(./text(),$target_tarm)"/> </xsl:variable> <xsl:variable name="non_change_after"> <xsl:value-of select="substring-after(./text(),$target_tarm)"/> </xsl:variable> <p><xsl:value-of select="$non_change_before"/><xsl:value-of select="$replace_tarm"/><xsl:value-of select="$non_change_after"/></p> </xsl:when> <xsl:otherwise> <xsl:copy-of select="."/> </xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet>

出力01:output01.xml

<topic> <title>吾輩は猫である。</title> <body> <section> <title>一</title> <p>【わたくし】は猫である。</p> <p>名前はまだ無い。</p> <p>どこで生れたかとんと見当がつかぬ。</p> <p>何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。</p> <p>【わたくし】はここで始めて人間というものを見た。</p> </section> </body> </topic>

【わたくし】が置換部分です。
change.xslの以下部分を、外部ファイルのリストに従って処理をさせたいです。

<xsl:variable name="target_tarm" select="'吾輩'"/> <xsl:variable name="change_tarm" select="'【わたくし】'"/>

とりあえず、3つの単語を置換するリストです。

外部ファイル:list.xml

<list> <para> <sequence>00001</sequence> <target>吾輩</target> <replace>【わたくし】</replace> </para> <para> <sequence>00002</sequence> <target>猫</target> <replace>【犬】</replace> </para> <para> <sequence>00003</sequence> <target>人間</target> <replace>【民間人】</replace> </para> </list>

希望する出力:output02.xml

<topic> <title>吾輩は猫である。</title> <body> <section> <title>一</title> <p>【わたくし】は【犬】である。</p> <p>名前はまだ無い。</p> <p>どこで生れたかとんと見当がつかぬ。</p> <p>何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。</p> <p>【わたくし】はここで始めて【民間人】というものを見た。</p> </section> </body> </topic>

次のXSLTで変換をしてみたのですが、1つのmuch=""に対して、外部ファイル内のfor-each分、処理が繰り返されてしまい、残念な結果しか得られませんでした。

XSLT:replace.xsl <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> <xsl:strip-space elements="*"/> <xsl:output indent="yes"/> <xsl:variable name="tarm_list" select="document('list.xml')"/> 《中略》 <xsl:template match="p">     <xsl:variable name="current_text" select="."/> <xsl:for-each select="$tarm_list//para"> <xsl:variable name="target_tarm" select="./target"/> <xsl:variable name="replace_tarm" select="./replace"/> <xsl:choose> <xsl:when test="contains($current_text,$target_tarm)"> <xsl:variable name="non_change_before"> <xsl:value-of select="substring-before($current_text,$target_tarm)"/> </xsl:variable> <xsl:variable name="non_change_after"> <xsl:value-of select="substring-after($current_text,$target_tarm)"/> </xsl:variable> <p><xsl:value-of select="$non_change_before"/><xsl:value-of select="$replace_tarm"/><xsl:value-of select="$non_change_after"/></p> </xsl:when> <xsl:otherwise> <p> <xsl:value-of select="$current_text"/> </p> </xsl:otherwise> </xsl:choose> </xsl:for-each> </xsl:template> </xsl:stylesheet>

残念な出力:output03.xml

<topic> <title>吾輩は猫である。</title> <body> <section> <title>一</title> <p>【わたくし】は猫である。</p> <p>吾輩は【犬】である。</p> <p>吾輩は猫である。</p> <p>名前はまだ無い。</p> <p>名前はまだ無い。</p> <p>名前はまだ無い。</p> <p>どこで生れたかとんと見当がつかぬ。</p> <p>どこで生れたかとんと見当がつかぬ。</p> <p>どこで生れたかとんと見当がつかぬ。</p> <p>何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。</p> <p>何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。</p> <p>何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。</p> <p>【わたくし】はここで始めて人間というものを見た。</p> <p>吾輩はここで始めて人間というものを見た。</p> <p>吾輩はここで始めて【民間人】というものを見た。</p> </section> </body> </topic>

外部ファイルのリスト項目を1つづつ照らし合わせながら、変換元ファイル(test.xml)を処理させるには、どうすればよろしいでしょうか。XSLTの誤りをご指摘いただけると助かります。
根本的に上記の方法ではNGな場合、別途の方法をご紹介いただけるとなお幸いです。
よろしくご教授のほど、お願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

仕様の詳細が不明なので、どこがどうということは言えませんが、これで「希望する出力」にはなると思います。

xml

1<xsl:stylesheet version="3.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" 2 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 3 4 <xsl:strip-space elements="*" /> 5 <xsl:output indent="yes" /> 6 7 <xsl:variable as="document-node(element(list))" name="term_list" select="document('list.xml')" /> 8 <xsl:variable as="element(para)+" name="paras" select="$term_list/list/para" /> 9 10 <xsl:mode on-no-match="shallow-copy" /> 11 12 <xsl:template as="text()" match="p/text()"> 13 <xsl:variable as="xs:string" name="original" select="." /> 14 15 <xsl:iterate select="$paras"> 16 <xsl:param as="xs:string" name="source" select="$original" /> 17 18 <xsl:on-completion> 19 <xsl:value-of select="$source" /> 20 </xsl:on-completion> 21 22 <xsl:next-iteration> 23 <xsl:with-param name="source" select="replace($source, target, replace, 'q')" /> 24 </xsl:next-iteration> 25 </xsl:iterate> 26 </xsl:template> 27 28</xsl:stylesheet>

投稿2020/04/13 17:15

編集2020/04/13 17:21
OACleaner

総合スコア72

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

UG_ito_Pcorp

2020/04/14 10:58

早速のご回答、ありがとうございました。 間違いなく、希望する出力が得られております。 学習するレベルを超えて、流用させていただくレベルですが、精進したいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問