使用XSL和Java将int值转换为颜色对象

时间:2012-12-27 09:49:50

标签: java xslt

我是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>

我有两个问题:

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>

任何人都可以帮我这个吗?提前谢谢

2 个答案:

答案 0 :(得分:0)

XSLT变量只能包含字符串,布尔值,数字或节点集 - Color:new(...)调用返回一个Java对象,该对象无法分配给XSLT变量,因此是异常。

可能的解决方案:

1)创建自己的扩展类,定义方法stringToRedstringToBlue等,以便它们接受一个字符串,将其内部转换为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>

这个apprach的问题是XSLT使用浮点算术,因此在某些情况下,舍入错误可能会导致组件的错误值。

答案 1 :(得分:0)

回答这个问题有点晚了,但是对于那些可以遇到同样问题的人来说,

对于indenation问题,我不得不使用自定义xsl模板来确保输出xml以我想要的方式进行。

该模板包含许多脏代码,这些代码强制xml标记具有模拟缩进的特殊间距

希望这有帮助:)