質問

XMLドキュメントの変換を試みています。私のXML変換は、特定の要素の値に応じて、2つの異なるタイプの基本要素になります。

<xsl:template match="/">
  <xsl:choose>
    <xsl:when test="/databean/data[@id='pkhfeed']/value/text()='200'">
      <xsl:call-template name="StructureA">
        <xsl:with-param name="structure" select="//databean" />
      </xsl:call-template>
    </xsl:when>
    <xsl:otherwise>
      <xsl:call-template name="StructureB">
        <xsl:with-param name="structure" select="//databean" />
      </xsl:call-template>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

StructureAまたはStructureBは、独自の名前空間とschemaLocationsを使用して作成されます。

<StructureA xmlns="http://...">

StructureA&amp; Bはいくつかの共通要素を共有するため、これらは&quot; xmlcommon.xslt&quot;という別のファイルで定義されます。両方の構造にテンプレートが含まれていること。このxmlcommonファイルには、StructureAまたはStructureBで定義された名前空間から使用できるようにしたいため、デフォルトの名前空間が定義されていません。ただし、トランスフォームを実行すると、共通ファイルからプルされたテンプレートは、空のxmlns属性になります。

<StructureA xmlns="http://...">
  <SharedElement xmlns="">Something</SharedElement>
</StructureA>

検証時には、正しい親の名前空間の代わりに空の名前空間が使用されます。 一般的なファイル内のテンプレートがこれらの空のxmlns属性を追加しないようにする方法を知っている人はいますか

一般的なファイルからの抜粋です:

<xsl:stylesheet version="1.0" xmlns:fn="http://www.w3.org/2005/02/xpath-functions" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:template name="ControlledListStructure">
    <xsl:param name="xmlElem" />
    <xsl:param name="structure" />

    <xsl:element name="{$xmlElem}">
      <!-- Blah blah blah -->
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>
役に立ちましたか?

解決

重要なことは、スタイルシートが結果ツリーに追加する各要素の名前を決定することです。要素の名前には、ローカル名と名前空間URIの2つの部分があります。上記のコードでは、ローカル名( $ xmlElem の値)を指定していますが、名前空間URIを指定していないため、デフォルトでは空の文字列になります。 (実際には、そのスタイルシートモジュールの既定の名前空間を使用します。ないため、空の文字列です。)つまり、要素は名前空間にないになります。ドキュメントをシリアル化するとき、XSLTプロセッサは xmlns =&quot;&quot; の非宣言を含めて、上部に表示されるデフォルトの名前空間の宣言を解除する必要があります。それ以外の場合、要素はそのネームスペースを使用しますが、これはスタイルシートが指示したものではありません。これを修正する最も邪魔にならない方法は、 $ xmlElem の場合と同様に、別のパラメーター(たとえば、 $ namespaceURI )を追加することです。次に、次のように記述します。

<xsl:element name="{$xmlElem}" namespace="{$namespaceURI}">

これで、結果の要素は、指定した名前空間を引き継ぐようになります(これにより、これらのデフォルトの名前空間未宣言を削除する効果があります)。

これで質問に答えるはずです。以下を無料のボーナス素材として提供します。 ;-)

値比較で text()ノードテストを削除する必要があります。テキストノードの値を直接比較する必要はほとんどありません。代わりに、要素自体の文字列値(すべての子孫テキストノードの文字列値の連結として定義される)を比較するだけです。これは次のようになります。

<xsl:when test="/databean/data[@id='pkhfeed']/value = '200'">

この方法で行う利点は、コメントが隠れていてもコードが壊れないことです:

<value>2<!--test-->00</value>

この場合、2つのテキストノード(&quot; 2&quot;と&quot; 00&quot;)があります。元のテストは、それらのいずれかが「200」に等しいかどうかを確認するため、失敗します。この場合、発生する可能性はほとんどありませんが、いずれの場合も、エレメントの文字列値(テキストノードの子とは対照的に)をテストすることは、それが意図する場合の良い習慣です。

最後に、テンプレートルールとXPathコンテキストについて学ぶことをお勧めします。 &lt; xsl:choose&gt; &lt; xsl:call-template&gt; 、および&lt; xsl:with-param&gt; を避ける傾向がありますいつでも可能なとき。まず、テンプレートルールは、XSLTのofい冗長な部分の多くを回避するのに役立ちます。

<xsl:template match="/databean[data[@id='pkhfeed']/value = '200']" priority="1">
  <StructureA xmlns="http://...">
    ...
  </StructureA>
</xsl:template>

<xsl:template match="/databean">
  <StructureB xmlns="http://...">
    ...
  </StructureB>
</xsl:template>

&lt; xsl:call-template&gt; を使用し続けても、現在のノードは変更されないため、 $ structure パラメーターを渡す必要はありません。呼び出されたテンプレート内。 StructureA のいずれかから簡単に // databean (または / databean にアクセスできます) StructureB テンプレート。現在のノードはまだ&quot; /&quot;なので、 (ドキュメントノード)。

XSLTのコア処理モデルとその最も強力な機能(テンプレートルール)について詳しく知りたい場合は、&quot; XSLTの仕組み&quot; 、私の XSLT 1.0ポケットリファレンスの無料サンプルの章。

これがあなたが交渉した以上のものであっても、あなたの役に立つことを願っています!

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top