[解決済み] xsltで文字列を文字列に置き換える
質問
ある文字列を別の文字列に置き換えたいのですが、それを行う例を見つけたのですが、うまくいかないようです。
<Addy>
<Row>
<LD>Dwelling, 1</D>
<LN> East</LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
<Row>
<LD>Logde</LD>
<LN>North </LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
</Addy>
次のような文字列をこのように置き換えたいのですが。
Dwelling = FLAT
Lodge = SHOP
以下は、私が使用したコードです。これは、LD要素内のすべての値を削除しただけです。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:lookup="lookup">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<lookup:data>
<LD code="Dwelling">FLAT</LD>
<LD code="Lodge">SHOP</LD>
</lookup:data>
<xsl:variable name="lookup" select="document('')/*/lookup:data"/>
<xsl:template match="LD/text()">
<xsl:value-of select="$lookup/LD[@code = current()]" />
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
上の入力データに適用すると、次のようになる。
<Addy>
<Row>
<LD></LD>
<LN> East</LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
<Row>
<LD></LD>
<LN>North </LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
</Addy>
適切なコードで期待される結果
<Addy>
<Row>
<LD>FLAT,1</D>
<LN> East</LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
<Row>
<LD>SHOP</LD>
<LN>North </LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
</Addy>
解決方法は?
以下は、文字列に複数の置換を行うためのXSLT変換で、拡張関数は必要ありません。 :
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="my:my">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<my:reps>
<rep>
<old>Dwelling</old>
<new>FLAT</new>
</rep>
<rep>
<old>Lodge</old>
<new>SHOP</new>
</rep>
</my:reps>
<xsl:variable name="vReps" select="document('')/*/my:reps/*"/>
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="LD/text()" name="replace">
<xsl:param name="pText" select="."/>
<xsl:choose>
<xsl:when test="not($vReps/old[contains($pText, .)])">
<xsl:value-of select="$pText"/>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="multiReplace">
<xsl:with-param name="pText" select="$pText"/>
<xsl:with-param name="pReps"
select="$vReps[contains($pText, old)]"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="multiReplace">
<xsl:param name="pText"/>
<xsl:param name="pReps"/>
<xsl:choose>
<xsl:when test="$pReps">
<xsl:variable name="vRepResult">
<xsl:call-template name="singleReplace">
<xsl:with-param name="pText" select="$pText"/>
<xsl:with-param name="pOld" select="$pReps[1]/old"/>
<xsl:with-param name="pNew" select="$pReps[1]/new"/>
</xsl:call-template>
</xsl:variable>
<xsl:call-template name="multiReplace">
<xsl:with-param name="pText" select="$vRepResult"/>
<xsl:with-param name="pReps" select="$pReps[position() >1]"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$pText"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="singleReplace">
<xsl:param name="pText"/>
<xsl:param name="pOld"/>
<xsl:param name="pNew"/>
<xsl:if test="$pText">
<xsl:choose>
<xsl:when test="not(contains($pText, $pOld))">
<xsl:value-of select="$pText"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="substring-before($pText, $pOld)"/>
<xsl:value-of select="$pNew"/>
<xsl:call-template name="singleReplace">
<xsl:with-param name="pText" select="substring-after($pText, $pOld)"/>
<xsl:with-param name="pOld" select="$pOld"/>
<xsl:with-param name="pNew" select="$pNew"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
提供された XML ドキュメントにこの変換が適用されたとき。
<Addy>
<Row>
<LD>Dwelling, 1</LD>
<LN> East</LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
<Row>
<LD>Lodge</LD>
<LN>North </LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
</Addy>
は、望んだ正しい結果を生成します。
<Addy>
<Row>
<LD>FLAT, 1</LD>
<LN> East</LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
<Row>
<LD>SHOP</LD>
<LN>North </LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
</Addy>
重要 :
この解答は完全で正しいものです。ショーンのものは、どちらかというと表面的なものです。
次のXML文書に適用して、2つのソリューションの結果を比較してください。 :
<Addy>
<Row>
<LD>Dwelling, Lodge, 1</LD>
<LN> East</LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
<Row>
<LD>Lodge, Dwelling</LD>
<LN>North </LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
</Addy>
Seanのソリューションでは、不正な置換が発生します。 :
<Addy>
<Row>
<LD>FLAT, Lodge, 1</LD>
<LN> East</LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
<Row>
<LD>Lodge, FLAT</LD>
<LN>North </LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
</Addy>
からの現在の正しい解答は これ の回答は、正しい置換を生成します。
<Addy>
<Row>
<LD>FLAT, SHOP, 1</LD>
<LN> East</LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
<Row>
<LD>SHOP, FLAT</LD>
<LN>North </LN>
<L>1</L>
<Tf>Abesinia Passage</Tf>
</Row>
</Addy>
説明 :
-
は アイデンティティルール は、実行のために選択されたすべてのマッチするノードをそのままコピーします。
-
の子テキストノードにマッチする1つのテンプレートで上書きされます。
LD
要素 -- 置換が行われなければならないノード。 -
このテンプレートは、マッチしたテキスト・ノードがいずれかの
old
(文字列の値) で指定された、グローバルなインラインのmy:reps
要素を使用します。便宜上、すべてのmy:reps/rep
という名前のグローバル変数で選択されています。$vReps
という変数があり、この変数から参照されます。これらの文字列のいずれもが現在のノードに含まれていない場合、出力にコピーされる。 -
もし、少なくとも1つの
$vReps/old
要素の文字列値が、現在マッチしているテキストノードに含まれている場合、置換を行う必要があります。ここでは"multiReplace"
は、現在のテキスト・ノードのすべての置換を実行する。このテンプレートにパラメータとして、現在のテキスト・ノードと、すべての$vReps/rep
要素の文字列値で、そのold
の子ノードが現在のテキストノードに含まれている場合、これらがすべて置換の対象となる。 -
は
multiReplace
という名前のテンプレートを呼び出します。singleReplace
という変数に取り込んで、最初の置換を行います。$vRepResult
. で置き換えた結果が格納されています。$pText
すべて の文字列の出現回数。$pReps[1]/old
の文字列値で$pReps[1]/new
. 次にmultiReplace
テンプレートは自分自身を再帰的に呼び出します。$pText
パラメータ、および最初の置換を除外した置換を行うノードセット -- を、このパラメータで指定します。$pReps
パラメータで指定します。この再帰の停止条件は$pReps
パラメータが空のノードセットになる。 -
は
singleReplace
テンプレートは、その名のとおり$pText
パラメータに等しい部分文字列があれば$pOld
パラメータに含まれる文字列でpNew
パラメータを使用します。置換の数は1より多くてもよいが、すべて1つの置換指定==>に対してである。したがって、名前singleReplace
. 置換は再び再帰的に行われ,停止条件は$pText
が空でなく、かつ$pOld
.
関連
-
[解決済み】JSF Faceletsのページを開くと、"このXMLファイルにはスタイル情報が関連付けられていないようです。"と表示される。
-
[解決済み】JSF Faceletsのページを開くと、"このXMLファイルにはスタイル情報が関連付けられていないようです。"と表示される。
-
[解決済み] i:nil="true "とはどういう意味ですか?
-
[解決済み] XML ファイルの構造から IMG タグを使用する方法
-
[解決済み] 大きなファイルのXML分割
-
[解決済み] デコード � リアルキャラクターへ
-
[解決済み] アンドロイドビューで頻繁に発生する問題、XMLのパースエラー:結合されていない接頭辞
-
xmlファイルを記述する際には、ルート要素に先行する文書内のマークアップが整形されている必要があります。
-
[解決済み] xsltで文字列を文字列に置き換える
-
[解決済み] JSONのXSLT対応
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】XML-スキーマでxsi:typeを属性として定義する方法とは?
-
[解決済み] エラーが発生しました。XMLドキュメントの構造は、同じエンティティ内で始まり、終わる必要があります。
-
[解決済み] i:nil="true "とはどういう意味ですか?
-
[解決済み] XMLファイルを別のXMLファイルに取り込むことはできますか?
-
[解決済み] 複数のタグを選択するXPath
-
[解決済み] xsltで文字列を文字列に置き換える
-
[解決済み】JSONとXMLの比較【クローズド
-
[解決済み】XMLで無効な文字とは?
-
[解決済み】XPathで子の子値を元に要素を選択する方法
-
[解決済み】XMLの "xmlns "の意味は?