XML和XSLT实现代码生成器(III)
 XSLT处理元数据(续)
   <!—命名模板,打印set方法à 
    <xsl:template name="printSetMethod"> 
        <xsl:param name="property"/> 
        <xsl:text>public void set</xsl:text> 
        <xsl:call-template name="translateHeadLetter">  <!—属性首字母需大写à 
            <xsl:with-param name="propertyName" select="name"/> 
        </xsl:call-template> 
        <xsl:text>(</xsl:text> 
        <xsl:value-of select="@type"/> 
        <xsl:text> </xsl:text> 
        <xsl:value-of select="name"/> 
        <xsl:text>)</xsl:text> 
        <xsl:if test="exception">     <!—输出任何方法抛出的异常 à 
            <xsl:text>throws </xsl:text> 
                    <xsl:apply-templates select="exception"/> 
        </xsl:if> 
        <xsl:text>{ this.</xsl:text>        <!—set方法主体à 
        <xsl:value-of select="name"/> 
        <xsl:text>=</xsl:text> 
        <xsl:value-of select="name"/> 
        <xsl:text>;}</xsl:text> 
    </xsl:template> 
    <!—命名模板,打印get方法à 
    <xsl:template name="printGetMethod"> 
        <xsl:param name="property"/> 
        <xsl:text>public </xsl:text> 
        <xsl:value-of select="@type"/> 
        <xsl:choose> 
            <xsl:when test="@type='boolean' or @type='java.lang.Boolean'"> 
                <xsl:text> is</xsl:text> 
            </xsl:when> 
            <xsl:otherwise> 
                <xsl:text> get</xsl:text> 
            </xsl:otherwise> 
        </xsl:choose> 
        <xsl:call-template name="translateHeadLetter"> 
            <xsl:with-param name="propertyName" select="name"/> 
        </xsl:call-template> 
        <xsl:text>()</xsl:text> 
        <xsl:if test="exception"> 
            <xsl:text>throws </xsl:text> 
                    <xsl:apply-templates select="exception"/> 
        </xsl:if> 
        <xsl:text>{ return </xsl:text> 
        <xsl:value-of select="name"/> 
        <xsl:text>;}</xsl:text> 
    </xsl:template> 
    <xsl:template name="translateHeadLetter"> 
        <xsl:param name="propertyName"/> 
        <xsl:variable name="length" select="string-length($propertyName)"/> 
        <xsl:variable name="headLetter" select="substring($propertyName,1,1)"/> 
<xsl:variable name="remainLetters" select="substring($propertyName,2,$length)"/> 
<xsl:value-of  
select="translate($headLetter,'abcdefghijklmnopqrstuvwxyz', 
'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/> 
        <xsl:value-of select="$remainLetters"/> 
    </xsl:template> 
    <xsl:template name="printDefaultValue"> 
        <xsl:param name="type"/> 
        <xsl:choose> 
            <xsl:when test="contains($type,'int')"> 
                <xsl:text>0</xsl:text> 
            </xsl:when> 
            <xsl:when test="contains($type,'boolean')"> 
                <xsl:text>false</xsl:text> 
            </xsl:when> 
            <xsl:when test="contains($type,'long')"> 
                <xsl:text>0</xsl:text> 
            </xsl:when> 
            <xsl:when test="contains($type,'float')"> 
                <xsl:text>0</xsl:text> 
            </xsl:when> 
            <xsl:when test="contains($type,'char')"> 
                <xsl:text>''</xsl:text> 
            </xsl:when> 
            <xsl:when test="contains($type,'String')"> 
                <xsl:text>""</xsl:text> 
            </xsl:when> 
            <xsl:otherwise> 
                <xsl:text>null</xsl:text> 
            </xsl:otherwise> 
        </xsl:choose> 
    </xsl:template> 
    <xsl:template match="exception"> 
        <xsl:value-of select="."/> 
        <xsl:if test="position()<last()"> 
            <xsl:text>,</xsl:text> 
        </xsl:if> 
    </xsl:template> 
列表1.3续 
不熟悉XSLT的读者可以参看[2]以便了解更多的信息。该XSL分析XML数据,针对匹配的元素将元数据转换为实际的Java代码。在支持XSLT的浏览器上如IE6可以直接键入XML文档的URL,就可以看见转换结果,注意:需要在XML中加入如下指令 
<?xml-stylesheet type="text/xsl" href="../xsl/javabean.xsl"?> 
  这样经过简单的两个步骤,代码转换的功能已经基本实现,只要利用一个简单的Java小程序就可以完成该代码生成器的初始模型。
简单代码生成器
列表1.5显示了一个这样目的的Java类。 
Package com.xs.xgen; 
Import javax.xml.transform.*; 
Import javax.xml.transform.stream.*; 
/** 
 * <p>Title: Code Generator based on XML and XSLT</p> 
 * <p>Description: Beta Version For Code Generator</p> 
 * <p>Copyright: xchu@Copyright (c) 2004</p> 
 * <p>Company: XS Group</p> 
 * @author Xingchen Chu 
 * @version 0.1 
 */ 
Public class SimpleCodeGenerator{ 
  public static void main(String [] args){ 
    if(args.length<3){ 
        System.err.println(“Usage : java SimpleCodeGenerator [xml] [xsl] [output]”); 
        System.exit(1); 
    } 
    try{ 
      Source xmlSource= 
          new javax.xml.transform.stream.StreamSource(new File(args[0])); 
      javax.xml.transform.Source xslSource= 
          new javax.xml.transform.stream.StreamSource(new File(args[1])); 
      javax.xml.transform.Result result= 
          new javax.xml.transform.stream.StreamResult(new File(args[2]); 
      TransformerFactory factory = TransformerFactory.newInstance(); 
      Transformer transformer = factory.newTransformer(xslSource); 
      Transformer.transform(xmlSource,result); 
    }catch(Exception e){ 
      e.printStackTrace(); 
    } 
  } 
列表1.4 
结果分析
       对于这个代码生成器来说,虽然基本的目的已经达到,机器已经完全可以自动的生成所有的代码,程序员只需要根据DTD编写一小段XML元数据即可,使用像XMLSpy这样的工具可以很容易编写出合适的XML元数据并可进行验证,然后使用java命令行即可得到想要的JavaBean类文件。而且如果想在现有的基础上添加更多的功能,比如支持索引属性,只需要稍微更改DTD以及XSL即可实现,如果还想为EJB生成基本接口文件,可以重新定义一个新的DTD和XSL,而不需要改变任何一点的Java代码。 
       然而,一切都还不完美。首先,XSLT的输出文本结果十分难阅读,因为XSLT在处理空格和缩近上能力有限,可读性好的结果文档是一个可以改进的方面;其次,程序员还是必须编写XML文件,并手动传递它和XSLT给代码生成器,这种静态方式可以被图形化的动态方式替代是更好的方案。本文的下一部分将说明这些问题并提出合适的解决方法。 
  
 
References
1.      Java and XSLT  Eric M. Burke  O’Reilly & Associates,Inc 2001 
2.      Essential XML  Don Box, Aaron Skonnard & John Lam  
Addison Wesley Longman, Inc. 2001 
 
Copyright: Xingchen Chu@Copyright (c) Reserved 2004  
 
  |