xslt转换xml文档&&xslt call java方法
经历了上一篇blog,,,发现很多东西会用容易,,,,能简单明了的说明其用法,,,还有点小难,,,,与不擅总结有关吧,,,好了,今天提笔在园里的第二篇blog,,来讲讲xslt转换xml文档以及xslt call java方法的一些使用方法,,写了个开头就不想往下写了有木有,,,唉。
1. 神马是xslt?
XSLT是扩展样式表转换语言(Extensible Stylesheet Language Transformations)的简称,这是一种对XML文档进行转化的语言。见下图。
XML Input: xml文档或者关系型数据库中的表
XSLT Code:xslt code用于转换xml文档(blog要介绍的内容哈)
XSLT Processor:xslt处理器,用于将xslt code连接到xml文档完成转换过程
Result Document:经过xslt转换后得到的文档
XSLT是XSL规范的一部分。XSL在转换XML文档时分为明显的两个过程,第一转换文档结构;其次将文档格式化输出。这两步可以分离开来并单独处理,因此XSL在发展过程中逐渐分裂为XSLT(结构转换)和XSL-FO(formatting objects)(格式化输出)两种分支语言,其中XSL-FO的作用就类似CSS在HTML中的作用。而我们这里重点讨论的是第一步的转换过程,也就是XSLT。
2. 直接上sample
2.1 xslt将xml文档转换成另一种xml格式
Input XML
1 <?xml version="1.0" encoding="utf-8"?> 2 <t-systems:Persons 3 xsi:schemaLocation="http://www.t-systems/2013/XMLExample" 4 xmlns:t-systems="http://www.t-systems.com/2013/XMLExample" 5 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 6 <Person> 7 <FirstName>David</FirstName> 8 <LastName>Beckham</LastName> 9 <BirthDay>811010</BirthDay> 10 <Age>32</Age> 11 </Person> 12 <Person> 13 <FirstName>John</FirstName> 14 <LastName>Beckham</LastName> 15 <BirthDay>810910</BirthDay> 16 <Age>33</Age> 17 </Person> 18 </t-systems:Persons>
Output XML
1 <?xml version="1.0" encoding="utf-8"?> 2 <SOAP-ENV:Envelop xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelop" 3 xmlns:t-systems="http://www.t-systems.com/2013/XMLExample"> 4 <SOAP-ENV:Body> 5 <t-systems:Persons> 6 <Person> 7 <Name>David Beckham</Name> 8 <BirthDay>1981-10-10</BirthDay> 9 <Age>32</Age> 10 </Person> 11 <Person> 12 <Name>John Beckham</Name> 13 <BirthDay>1981-09-10</BirthDay> 14 <Age>33</Age> 15 </Person> 16 </t-systems:Persons> 17 </SOAP-ENV:Body> 18 </SOAP-ENV:Envelop>
XSLT Code
1 <?xml version="1.0" encoding="utf-8"?> 2 <xsl:stylesheet version="1.0" 3 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 4 xmlns:t-systems="http://www.t-systems.com/2013/XMLExample" 5 xmlns:xs="http://www.w3.org/2001/XMLSchema" 6 xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 7 exclude-result-prefixes="xs"> 8 <xsl:output method="xml" encoding="UTF-8" indent="no" /> 9 <!-- Entry mapping --> 10 <xsl:template match="/"> 11 <SOAP-ENV:Envelope> 12 <SOAP-ENV:Body> 13 <xsl:for-each select="/t-systems:Persons"> 14 <t-systems:Persons> 15 <xsl:for-each select="Person"> 16 <Person> 17 <Name> 18 <xsl:call-template name="ConvertName"> 19 <xsl:with-param name="firstname" 20 select="FristName" /> 21 <xsl:with-param name="lastname" 22 select="LastName" /> 23 </xsl:call-template> 24 </Name> 25 <BirthDay> 26 <xsl:call-template name="convert-string-date"> 27 <xsl:with-param name="input" 28 select="BirthDay" /> 29 </xsl:call-template> 30 </BirthDay> 31 <Age> 32 <xsl:value-of select="Age" /> 33 </Age> 34 </Person> 35 </xsl:for-each> 36 </t-systems:Persons> 37 </xsl:for-each> 38 </SOAP-ENV:Body> 39 </SOAP-ENV:Envelope> 40 </xsl:template> 41 <!-- Concat FirstName and Last Name --> 42 <xsl:template name="ConvertName"> 43 <xsl:param name="firstname" /> 44 <xsl:param name="lastname" /> 45 <xsl:value-of select="concat($firstname,' ',$lastname)" /> 46 </xsl:template> 47 <!-- Convert String to Date --> 48 <!-- Convert Date format from String into Date --> 49 <xsl:template name="convert-string-date"> 50 <xsl:param name="input" /> 51 <xsl:variable name="year" 52 select="concat('19',substring($input,5,2))" /> 53 <xsl:variable name="month" select="substring($input,3,2)" /> 54 <xsl:variable name="day" select="substring($input,1,2)" /> 55 <xsl:value-of select="concat($year,'-',$month,'-',$day)" /> 56 </xsl:template> 57 </xsl:stylesheet>
XSLT Processer
万事俱备,,只差一把东风了:xslt processer。推荐一款必备软件哈,,,Altova XMLSpy,,,专注XML文档process的一个利器。使用方法是,先打开xml input文档,点击XSL/XQuery这个菜单—>XSL转换,,,选取XSLT Code文件就OK了哈。。。不过,这个工具对于call java方法的xslt code文件就不好使了,,对于call java方法的xslt code,java有自己的xml格式转换API—jdk1.5自带的包javax.xml.transform,,会在下面介绍。
xslt中有一个很重要的概念就是:xsl:template.有两种template:named template和template rule. xsl:template元素带name属性的是named template;xsl:template元素带match属性的是template rule.用call-template去使用named template;用apply-template去使用template rule。示例中即有named template也有template rule.
来详细看看sample code中named template的使用方法:
先定义template:
1 <xsl:template name="ConvertName"> 2 <xsl:param name="firstname" /> 3 <xsl:param name="lastname" /> 4 <xsl:value-of select="concat($firstname,' ',$lastname)" /> 5 </xsl:template>
再使用template:
<xsl:call-template name="ConvertName"> <xsl:with-param name="firstname" select="FristName" /> <xsl:with-param name="lastname" select="LastName" /> </xsl:call-template>
PS:发现了一个笔误,应该为select="FirstName",而不是select="FristName",这个错误在xslt code中也有,后来发现改起来还蛮麻烦,就没有改。
有木有觉得很像方法的调用啊,,,,,xsl:with-param中定义形参;xsl:param中传入实参,,,,然后根据name来调用啊啊啊啊,,,,
xslt code文件的header中还要定义好namespace:命名空间即要定义好xslt本身的命名空间,还要定义input xml和output xml文件中的命名空间,作用是为了使用xpath找到文件中的元素。
2.2 xslt将xml文档转换成html格式
先看下output:
XSLT Code:
1 <?xml version="1.0" encoding="utf-8"?> 2 <xsl:stylesheet version="1.0" 3 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 4 xmlns:t-systems="http://www.t-systems.com/2013/XMLExample" 5 xmlns:xs="http://www.w3.org/2001/XMLSchema" 6 xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 7 exclude-result-prefixes="xs"> 8 <xsl:output method="html" encoding="UTF-8" indent="no" /> 9 <!-- Entry mapping --> 10 <xsl:template match="/"> 11 <body> 12 <xsl:for-each select="/t-systems:Persons"> 13 <center> 14 <table border="1"> 15 <tr> 16 <th>Name</th> 17 <th>BirthDay</th> 18 <th>Age</th> 19 </tr> 20 <xsl:for-each select="Person"> 21 <tr> 22 <td> 23 <xsl:call-template name="ConvertName"> 24 <xsl:with-param name="firstname" 25 select="FirstName" /> 26 <xsl:with-param name="lastname" 27 select="LastName" /> 28 </xsl:call-template> 29 </td> 30 <td> 31 <xsl:call-template name="convert-string-date"> 32 <xsl:with-param name="input" 33 select="BirthDay" /> 34 </xsl:call-template> 35 </td> 36 <td> 37 <xsl:value-of select="Age" /> 38 </td> 39 </tr> 40 </xsl:for-each> 41 </table> 42 </center> 43 </xsl:for-each> 44 </body> 45 </xsl:template> 46 <!-- Concat FirstName and Last Name --> 47 <xsl:template name="ConvertName"> 48 <xsl:param name="firstname" /> 49 <xsl:param name="lastname" /> 50 <xsl:value-of select="concat($firstname,' ',$lastname)" /> 51 </xsl:template> 52 <!-- Convert String to Date --> 53 <!-- Convert Date format from String into Date --> 54 <xsl:template name="convert-string-date"> 55 <xsl:param name="input" /> 56 <xsl:variable name="year" 57 select="concat('19',substring($input,5,2))" /> 58 <xsl:variable name="month" select="substring($input,3,2)" /> 59 <xsl:variable name="day" select="substring($input,1,2)" /> 60 <xsl:value-of select="concat($year,'-',$month,'-',$day)" /> 61 </xsl:template> 62 </xsl:stylesheet>
好伐,,,,下面开讲xslt call java方法喽。
3. XSLT call java方法
对于xslt中转换name的显示方式的例子,,,,我们不用template做,,,,改成用java方法来做。如下:
1 public class TestCallJavaMethod { 2 3 public static String convertName(String firstName, String lastName){ 4 5 return firstName+" "+lastName; 6 } 7 }
详细步骤来了:
3.1 将java class加入xslt code的namespace中
xmlns:javacode="demo.TestCallJavaMethod” exclude-result-prefixes="xs javacode"
demo是java class存放的包名;exclude-result-prefixes用来表示在output xml中不显示xs和javacode这两个命名空间前缀。
3.2 定义xslt变量去存储参数的值
先从input xml获取firstName和lastName的值
<xsl:variable name="firstName" select="FirstName" />
<xsl:variable name="lastName" select="LastName" />
3.3 XSLT转换xml文档—call java方法
<xsl:variable name="convertName" select="javacode:convertName($firstName,$lastName)" />
<xsl:value-of select="$convertName" />
用call java方法实现2.1中转换xml文档
XSLT Code
1 <?xml version="1.0" encoding="UTF-8"?> 2 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 3 xmlns:t-systems="http://www.t-systems.com/2013/XMLExample" 4 xmlns:javacode="demo.TestCallJavaMethod” 5 xmlns:xs="http://www.w3.org/2001/XMLSchema" 6 xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" exclude-result-prefixes="xs javacode"> 7 <xsl:output method="xml" encoding="UTF-8" indent="no"/> 8 <!-- Entry mapping --> 9 <xsl:template match="/"> 10 <SOAP-ENV:Envelope> 11 <SOAP-ENV:Body> 12 <xsl:for-each select="/t-systems:Persons"> 13 <t-systems:Persons> 14 <xsl:for-each select="Person"> 15 <Person> 16 <Name> 17 <xsl:variable name="firstName" select="FirstName" /> 18 <xsl:variable name="lastName" select="LastName" /> 19 <xsl:variable name="convertName" select="javacode:convertName($firstName,$lastName)" /> 20 <xsl:value-of select="$convertName" /> 21 </Name> 22 <BirthDay> 23 <xsl:call-template name="convert-string-date"> 24 <xsl:with-param name="input" select="BirthDay" /> 25 </xsl:call-template> 26 </BirthDay> 27 <Age><xsl:value-of select="Age" /></Age> 28 </Person> 29 </xsl:for-each> 30 </t-systems:Persons> 31 </xsl:for-each> 32 </SOAP-ENV:Body> 33 </SOAP-ENV:Envelope> 34 </xsl:template> 35 <!-- Convert String to Date --> 36 <!-- Convert Date format from String into Date --> 37 <xsl:template name="convert-string-date"> 38 <xsl:param name="input" /> 39 <xsl:variable name="year" 40 select="concat('19',substring($input,5,2))" /> 41 <xsl:variable name="month" select="substring($input,3,2)" /> 42 <xsl:variable name="day" select="substring($input,1,2)" /> 43 <xsl:value-of select="concat($year,'-',$month,'-',$day)" /> 44 </xsl:template> 45 </xsl:stylesheet>
用于transform的JAVA Code
1 package demo; 2 3 import java.io.IOException; 4 5 import javax.xml.transform.OutputKeys; 6 import javax.xml.transform.Result; 7 import javax.xml.transform.Source; 8 import javax.xml.transform.Transformer; 9 import javax.xml.transform.TransformerException; 10 import javax.xml.transform.TransformerFactory; 11 import javax.xml.transform.stream.StreamResult; 12 import javax.xml.transform.stream.StreamSource; 13 14 public class TransformerDemo { 15 16 public static void main(String[] args) throws TransformerException, IOException { 17 Source source = new StreamSource("src/com/demo/input2.xml"); 18 Source xsl = new StreamSource("src/com/demo/sample3.xsl"); 19 Result result = new StreamResult(System.out); 20 21 TransformerFactory factory = TransformerFactory.newInstance(); 22 Transformer transformer = factory.newTransformer(xsl); 23 transformer.setOutputProperty(OutputKeys.INDENT, "yes"); 24 transformer.transform(source, result); 25 } 26 27 }
Tips:XSLT Call Java方法只能call java 中的static方法哈,,,切记啊,,,,xslt若想call java中的字段的话(如firstName),应先把字段用get()方法转换成static(getFirstName()),,再用xslt去call getFirstName()这个方法就好了。。。
另外,如果直接将xml,或者xsl文件的内容copy下来用于新建文件的时候,可能会出现“org.xml.sax.SAXParseException: Content is not allowed in prolog”的异常,这是因为有些编辑器会给文本加上BOM头。解决方案就是去除BOM头就可以了。怎么去?百度一下,你就知道。怎么验证是否去除成功?使用NotePad++,或者UltraEdit,或者EditPlus以十六进制的方式打开就可以看到了哈。
OMG,终于说完,,,,第二篇blog了,,,自豪瓦。。。。。。