0

私は XSL の初心者で、int RGB カラーを表すタグを含む xml ファイルを持っています。XSL を使用してそれらを Color オブジェクト タグに変換したいと考えています。

私のxmlにはこれらのタグが含まれています

<?xml version="1.0" encoding="UTF-8"?>
.
.
.
<ForeGroundColour>-16776961</ForeGroundColour>
.
.
.
</xml>

必要な xml は次のとおりです。

<ForeGroundColour>
  <red>102</red>
  <blue>102</blue>
  <green>255</green>
  <alpha>255</alpha>
</ForeGroundColour>

私のXSLファイルは次のとおりです。

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:Color="java.awt.Color"
    xmlns:Integer="java.lang.Integer" exclude-result-prefixes="Color Integer ">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />

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

    <xsl:template match="//*[contains(name(),'ForegroundColour')]">
        <xsl:copy>
            <xsl:variable name="rgb" select="." />
            <xsl:variable name="color" select="Color:new(Integer:parseInt($rgb))" />
            <xsl:element name="red">
                <xsl:value-of select="Color:getRed($color)" />
            </xsl:element>
            <xsl:element name="blue">
                <xsl:value-of select="Color:getBlue($color)" />
            </xsl:element>
            <xsl:element name="green">
                <xsl:value-of select="Color:getGreen($color)" />
            </xsl:element>
            <xsl:element name="alpha">
                <xsl:value-of select="Color:getAlpha($color)" />
            </xsl:element>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

2 つの問題があります。

1- このコードを実行すると、次の例外が発生します。

Exception in thread "main" java.lang.VerifyError: (class: transformer, method: template$dot$1 signature: (Lcom/sun/org/apache/xalan/internal/xsltc/DOM;Lcom/sun/org/apache/xml/internal/dtm/DTMAxisIterator;Lcom/sun/org/apache/xml/internal/serializer/SerializationHandler;I)V) Expecting to find double on stack
    at java.lang.Class.getDeclaredConstructors0(Native Method)
    at java.lang.Class.privateGetDeclaredConstructors(Class.java:2389)
    at java.lang.Class.getConstructor0(Class.java:2699)
    at java.lang.Class.newInstance0(Class.java:326)
    at java.lang.Class.newInstance(Class.java:308)
    at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.getTransletInstance(TemplatesImpl.java:364)
    at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.newTransformer(TemplatesImpl.java:394)
    at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl.newTransformer(TransformerFactoryImpl.java:649)
    at com.nyfix.ostp.server.workspacemigrator.XMLTransformer.transform(XMLTransformer.java:44)
    at com.nyfix.ostp.server.workspacemigrator.XSLMigrator.migrate(XSLMigrator.java:45)
    at com.nyfix.ostp.server.workspacemigrator.WorkspaceMigratorFactory.<init>(WorkspaceMigratorFactory.java:19)
    at com.nyfix.ostp.server.workspacemigrator.WorkspaceMigratorFactory.main(WorkspaceMigratorFactory.java:45)

2-挿入されたノードをテストするためだけにテンプレートを使用すると、

<xsl:template match="//*[contains(name(),'ForegroundColour')]">
    <xsl:copy>
        <xsl:variable name="rgb" select="." />
        <xsl:element name="red">
            <xsl:value-of select="$rgb" />
        </xsl:element>
        <xsl:element name="blue">
            <xsl:value-of select="$rgb" />
        </xsl:element>
        <xsl:element name="green">
            <xsl:value-of select="$rgb" />
        </xsl:element>
        <xsl:element name="alpha">
            <xsl:value-of select="$rgb" />
        </xsl:element>
    </xsl:copy>
</xsl:template>

xml はインデントなしで変換されます。

                      <ForegroundColour>
<red>-16776961</red>
<blue>-16776961</blue>
<green>-16776961</green>
<alpha>-16776961</alpha>
</ForegroundColour>

誰でもこれで私を助けることができますか?前もって感謝します

4

2 に答える 2

0

XSLT 変数には、文字列、ブール値、数値、またはノード セットのみを含めることができます。Color:new(...)呼び出しは、XSLT 変数に割り当てることができない Java オブジェクトを返すため、例外になります。

可能な解決策:

stringToRed1) メソッドなどを定義して独自の拡張クラスを作成しstringToBlue、文字列を受け入れ、内部でColorオブジェクトに変換してから、必要なコンポーネント (赤、青など) を数値または文字列として抽出します。これらの関数は、直接使用できます。

<xsl:element name="red">
  <xsl:value-of select="MyColorFunctions:stringToRed(.)" />
</xsl:element>

2) 整数で表現された色をその成分に変換するアルゴリズムを「リバースエンジニアリング」し、拡張関数を使わずにXSLTで直接実装する。通常、赤のコンポーネントは最下位 8 ビット、青は次の 8 ビットなど (またはその逆) になり、負の値を処理する必要があります (2 の補数から絶対値に変換する) - このようなもの:

  <xsl:variable name="color">
    <xsl:choose>
      <xsl:when test="number(.) &gt;=0">
        <xsl:value-of select="number(.)"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="4278190080+number(.)"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>
  <red>
    <xsl:value-of select="floor($color mod 256)" />
  </red>
  <green>
    <xsl:value-of select="floor(($color div 256) mod 256)" />
  </green>
  <blue>
    <xsl:value-of select="floor(($color div 65536) mod 256)" />
  </blue>
  <alpha>
    <xsl:value-of select="floor(($color div 16777216) mod 256)" />
  </alpha>

このアプローチの問題は、XSLT が浮動小数点演算を使用することです。そのため、場合によっては、丸め誤差によってコンポーネントの値が正しくなくなる可能性があります。

于 2012-12-27T18:10:12.693 に答える