0

変換する必要があるシナリオがあります:

<Hand id="left">
    <FingerOne>Thumb</FingerOne>
    <FingerTwo>Pointer</FingerTwo>
    <FingerThree>Middle</FingerThree>
</Hand>

に:

<Hand id="left" F1="Thumb" F2="Pointer" F3="Middle" />

この XSLT の一部を使用して、ネストされたエンティティ タグを属性に変換してきましたが、うまくいきました。要素を属性に移動しながら、名前「FingerOne」を1、「FingerTwo」を2などに変更する方法がわかりません。

<xsl:for-each select="*">
    <xsl:attribute name="{name()}">
        <xsl:value-of select="text()"/>
    </xsl:attribute>
</xsl:for-each>

この回答https://stackoverflow.com/a/8274527/857994を見つけました。これは、基本的にマップを使用して変換を行う方法を示しています。ただし、ドキュメントで機能させることはできないようです。

JAXP を使用して XSLT 機能の Java のビルドでこれを機能させようとしていることに注意してください。XSLT2.0 の多くの機能をサポートしていないようです。

4

2 に答える 2

3

これは自己完結型で、外部の XML ファイルを必要としないオプションです。

この XSLT の場合:

<?xml version="1.0"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:my="my"
  exclude-result-prefixes="my"
  version="1.0">
  <xsl:output omit-xml-declaration="yes" indent="yes"/>
  <xsl:strip-space elements="*"/>

  <my:attributeNames>
    <name original="FingerOne" new="F1"/>
    <name original="FingerTwo" new="F2"/>
    <name original="FingerThree" new="F3"/>
  </my:attributeNames>

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="Hand/*">
    <xsl:attribute
      name="{document('')/*/my:attributeNames/*
                            [@original = name(current())]/@new}">
      <xsl:value-of select="."/>
    </xsl:attribute>
  </xsl:template>
</xsl:stylesheet>

...提供された XML に対して適用されます。

<Hand id="left">
  <FingerOne>Thumb</FingerOne>
  <FingerTwo>Pointer</FingerTwo>
  <FingerThree>Middle</FingerThree>
</Hand>

...必要な結果が生成されます。

<Hand id="left" F1="Thumb" F2="Pointer" F3="Middle" />

説明:

  • <my:attributeNames>要素の「配列」に注意してください。さらに、「古い」値と「新しい」値がこれらの要素に属性として含まれていることに注意してください。

  • document('')これらの値は、現在のドキュメントから要素を収集するようにパーサーに指示する命令を使用してアクセスされます。


または、別の XSLT 1.0 ソリューションを次に示します。次の場合は、より便利になる可能性があります。

  • document('')何らかの理由で、あなたの環境では利用できません。

また

  • XSLT で疑似辞書を使用するのは、少し手間がかかるように思えます (そして、小さな仮定を立てても構いません)。

この XSLT の場合:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output omit-xml-declaration="yes" indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:variable name="vStartingChar" select="'F'" />

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="Hand/*">
    <xsl:attribute
      name="{concat($vStartingChar, count(preceding-sibling::*) + 1)}">
      <xsl:value-of select="."/>
    </xsl:attribute>
  </xsl:template>
</xsl:stylesheet>

...同じ入力 XML に対して適用すると、必要な結果が再び生成されます。

<Hand id="left" F1="Thumb" F2="Pointer" F3="Middle" />

説明:

XSLT の先頭に定義されている変数に注意してください。

<xsl:variable name="vStartingChar" select="'F'" />

これにより、新しい属性の開始文字に変更するための便利なメカニズムが提供されます。前述のように、この同じパターンが続く場合 (つまり、追加の属性が同じスキームに従う場合 - F4F5など)、要素の「配列」を更新する必要がないため、このソリューションはより良い方法です。

于 2013-04-30T01:33:52.810 に答える
1

辞書のアプローチを使用する場合は、最初に次の名前のファイルに辞書を作成する必要がありますdict.xml

<dict>
    <entry name="FingerOne">F1</entry>
    <entry name="FingerTwo">F2</entry>
    <entry name="FingerThree">F3</entry>
</dict>

次に、次のように変換を記述できます。

<xsl:variable name="dict" select="document('dict.xml')/dict"/>

<xsl:template match="Hand">
    <xsl:copy>
        <xsl:copy-of select="@*"/>
        <xsl:apply-templates select="*" mode="map-to-attr"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="*" mode="map-to-attr">
    <xsl:attribute name="{$dict/entry[@name=name(current())]}">
        <xsl:value-of select="."/>
    </xsl:attribute>
</xsl:template>
于 2013-04-30T00:18:55.067 に答える