Smooks转换设计
生活随笔
收集整理的這篇文章主要介紹了
Smooks转换设计
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
Smooks轉(zhuǎn)換設(shè)計(jì)
背景
不同的合作銀行對(duì)應(yīng)的外部接口是不一樣的,我們需要把外部這些變化不定的接口格式,轉(zhuǎn)換為我們銀保通系統(tǒng)可以識(shí)別的內(nèi)部接口.Smooks可以很好的解決這一問題.并且,當(dāng)合作銀行的接口隨著業(yè)務(wù)的變化而發(fā)生變化時(shí),smooks只需要通過變更轉(zhuǎn)換模板,就可以實(shí)現(xiàn)對(duì)變化后接口的支持。
Smooks框架可以在smooks的官網(wǎng)www.smooks.org (需要FQ軟)下載。本文smooks的版本是smooks-1.4。在其lib文件夾中是所需要的jar包。將所有jar包導(dǎo)入你的工程中,就能使用smooks進(jìn)行報(bào)文解析了。
現(xiàn)在說明下面兩種種轉(zhuǎn)換:XmlToXml,CsvToXml.
1. Xml To Xml
說明xml轉(zhuǎn)換為xml在smooks的配置中有兩種方式,一種是通過xsl模板控制,一種是通過freemaker模板控制。其中后者比較靈活,格式容易控制,推薦使用后者。
1.1 use xsl Templating
工程名為MyXmlToXml①.需要轉(zhuǎn)換的報(bào)文:文件名在程序中定為input-message.xml
<?xml version="1.0" encoding="GBK"?> <PACKET type="REQUEST" version="1.0"> <HEAD> <TRANSTYPE>SYN</TRANSTYPE> <TRANSCODE>100006</TRANSCODE> <USER>eies</USER> <PASSWORD>eies</PASSWORD> <SVCSEQNO></SVCSEQNO > </HEAD> <THIRD> <EXTENTERPCODE>19002020102</EXTENTERPCODE> <EXTPROVCODE>24</EXTPROVCODE> <EXTAREACODE>0187</EXTAREACODE> <EXTSITECODE>0187</EXTSITECODE> <EXTSEQUENCENO>200804060001</EXTSEQUENCENO> <TRANSDATE>2009-08-06</TRANSDATE> <TRANSTIME>12:30:30</TRANSTIME> <EXTOPERATORCODE>2020</EXTOPERATORCODE> </THIRD> <BODY> <POLICYNO>110880829200904000016</POLICYNO> <C_PASSWORD /> </BODY> </PACKET>②.配置轉(zhuǎn)化的配置文件,在程序中名為smooks-config.xml:
<?xml version='1.0' encoding='UTF-8'?>
<smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.0.xsd"><!-- HEAD --><resource-config selector="HEAD"><resource type="xsl"><![CDATA[<HEAD><SVCTYPE><xsl:value-of select="./TRANSTYPE" /></SVCTYPE><SVCCODE><xsl:value-of select="./TRANSCODE" /></SVCCODE><SVCNAME><xsl:value-of select="./USER" /></SVCNAME><SVCSEQNO><xsl:value-of select="./PASSWORD" /></SVCSEQNO><SVCSTATUS>000000</SVCSTATUS><SVCMESSAGE></SVCMESSAGE><SVCDETAIL>QueryPolicyByProposalNoService</SVCDETAIL></HEAD>]]></resource><param name="is-xslt-templatelet">true</param></resource-config><!-- THIRD --><resource-config selector="THIRD"><resource type="xsl"><![CDATA[<THIRD><EXTENTERPCODE><xsl:value-of select="./EXTENTERPCODE" /></EXTENTERPCODE><EXTPROVCODE><xsl:value-of select="./EXTPROVCODE" /></EXTPROVCODE><EXTAREACODE><xsl:value-of select="./EXTAREACODE" /></EXTAREACODE><EXTSITECODE><xsl:value-of select="./EXTSITECODE" /></EXTSITECODE><EXTSEQUENCENO><xsl:value-of select="./EXTSEQUENCENO" /></EXTSEQUENCENO><TRANSDATE><xsl:value-of select="./TRANSDATE" /></TRANSDATE><TRANSTIME><xsl:value-of select="./TRANSTIME" /></TRANSTIME><EXTOPERATORCODE><xsl:value-of select="./EXTOPERATORCODE" /></EXTOPERATORCODE></THIRD>]]></resource><param name="is-xslt-templatelet">true</param></resource-config> <!-- BODY --><resource-config selector="BODY"><resource type="xsl"><![CDATA[<BASE_LIST><BASE_DATA><C_PLY_NO><xsl:value-of select="./POLICYNO" /></C_PLY_NO><C_PASSWORD><xsl:value-of select="./C_PASSWORD" /></C_PASSWORD> </BASE_DATA></BASE_LIST> ]]></resource><param name="is-xslt-templatelet">true</param></resource-config>
</smooks-resource-list>說明此配置文件的作用是通過內(nèi)置xsl的配置將input-message.xml中的一些標(biāo)簽名替換掉,例如:
將<TRANSTYPE>替換成</SVCTYPE>,新增加一些丟失的標(biāo)簽例如<SVCDETAIL>QueryPolicyByProposalNoService</SVCDETAIL>,并且將<BODY> 標(biāo)簽下的內(nèi)容改為一個(gè)list類型的標(biāo)簽。結(jié)果請(qǐng)對(duì)照下面out.xml。
③.通過如下程序可讀取輸入報(bào)文input-message.xml和配置文件smooks-config.xml,并產(chǎn)生輸出文件out.xml.
package example;import org.milyn.Smooks;
import org.milyn.SmooksException;
import org.milyn.io.StreamUtils;
import org.xml.sax.SAXException;import javax.xml.transform.stream.StreamSource;
import javax.xml.transform.stream.StreamResult;
import java.io.*;public class Main {//讀入輸入報(bào)文private static byte[] messageIn = readInputMessage();/*** 主方法*/public static void main(String[] args) throws IOException, SAXException, SmooksException {String messageOut = Main.runSmooksTransform();StreamUtils.writeFile(new File("out.xml"),messageOut.getBytes()); //將輸出報(bào)文寫出到文件out.xml
}/*** 根據(jù)配置文件輸入報(bào)文的byte[]轉(zhuǎn)化為輸出報(bào)文的String* 利用smooks進(jìn)行轉(zhuǎn)化*/protected static String runSmooksTransform() throws IOException, SAXException, SmooksException {// 讀取配置文件smooks-config.xmlSmooks smooks = new Smooks("smooks-config.xml");try {CharArrayWriter outputWriter = new CharArrayWriter(); //存入smooks的轉(zhuǎn)化結(jié)果存入CharArrayWriter的對(duì)象,該類繼承java.io.writer//調(diào)用smooks.filterSource方法,進(jìn)行smooks轉(zhuǎn)化。smooks.filterSource(new StreamSource(new ByteArrayInputStream(messageIn)), new StreamResult(outputWriter));return outputWriter.toString(); //將轉(zhuǎn)化結(jié)果轉(zhuǎn)化為字符串} finally {smooks.close();}}/*** 讀入輸入報(bào)文* @return 輸入報(bào)文的byte[]*/private static byte[] readInputMessage() {try {return StreamUtils.readStream(new FileInputStream("input-message.xml"));} catch (IOException e) {e.printStackTrace();return "<no-message/>".getBytes();}}
}④.輸出的報(bào)文out.xml:<PACKET type="REQUEST" version="1.0"> <HEAD><SVCTYPE>SYN</SVCTYPE><SVCCODE>100006</SVCCODE><SVCNAME>eies</SVCNAME><SVCSEQNO>eies</SVCSEQNO><SVCSTATUS>000000</SVCSTATUS><SVCMESSAGE></SVCMESSAGE><SVCDETAIL>QueryPolicyByProposalNoService</SVCDETAIL></HEAD> <THIRD><EXTENTERPCODE>19002020102</EXTENTERPCODE><EXTPROVCODE>24</EXTPROVCODE><EXTAREACODE>0187</EXTAREACODE><EXTSITECODE>0187</EXTSITECODE><EXTSEQUENCENO>200804060001</EXTSEQUENCENO><TRANSDATE>2009-08-06</TRANSDATE><TRANSTIME>12:30:30</TRANSTIME><EXTOPERATORCODE>2020</EXTOPERATORCODE></THIRD> <BASE_LIST><BASE_DATA><C_PLY_NO>110880829200904000016</C_PLY_NO><C_PASSWORD></C_PASSWORD></BASE_DATA></BASE_LIST>
</PACKET>
1.2 use freemaker Templating
工程名為:MyXmlToXmlWithFreemaker①.需要轉(zhuǎn)換的報(bào)文:文件名在程序中定為input-message.xml
<order id='332'> <header> <customer number="123">Joe</customer> </header> <order-items> <order-item id='1'> <product>1</product> <quantity>2</quantity> <price>8.80</price> </order-item> <order-item id='2'> <product>2</product> <quantity>3</quantity> <price>10.90</price> </order-item><!--可能還有 --> </order-items>
</order>②.配置轉(zhuǎn)化的配置文件,在程序中名為smooks-config.xml:
<?xml version="1.0"?><smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd" xmlns:ftl="http://www.milyn.org/xsd/smooks/freemarker-1.1.xsd"> <!-- Filter the message using the SAX Filter (i.e. not DOM, so no intermediate DOM for the "complete" message - there are "mini" DOMs for the NodeModels below).... --> <params> <param name="stream.filter.type">SAX</param> <param name="default.serialization.on">false</param> </params> <!-- Create 2 NodeModels. One high level model for the "order" (header etc) and then one per "order-item". These models are used in the FreeMarker templating resources defined below. You need to make sure you set the selector such that the total memory footprint is as low as possible. In this example, the "order" model will contain everything accept the <order-item> data (the main bulk of data in the message). The "order-item" model only contains the current <order-item> data (i.e. there's max 1 order-item in memory at any one time). --> <resource-config selector="order,order-item"> <resource>org.milyn.delivery.DomModelCreator</resource> </resource-config><!-- Apply the first part of the template when we reach the startof the <order-items> element. Apply the second part when we reach the end. Note the <?TEMPLATE-SPLIT-PI?> Processing Instruction in the template. This tells Smooks where to split the template, resulting in the order-items being inserted at this point. --> <ftl:freemarker applyOnElement="order-items"> <ftl:template><!--<?xml version="1.0" encoding="GBK"?>
<salesorder type="REQUEST" version="1.0"> <details> <orderid>${order.@id}</orderid> <customer> <id>${order.header.customer.@number}</id> <name>${order.header.customer}</name> </customer> </details> <itemList> <?TEMPLATE-SPLIT-PI?> </itemList>
</salesorder>--></ftl:template> </ftl:freemarker> <!-- Output the <order-items> elements. This will appear in the output message where the <?TEMPLATE-SPLIT-PI?> token appears in the order-items template. --> <ftl:freemarker applyOnElement="order-item"> <ftl:template><!-- <item> <id>${.vars["order-item"].@id}</id> <productId>${.vars["order-item"].product}</productId> <quantity>${.vars["order-item"].quantity}</quantity> <price>${.vars["order-item"].price}</price> </item>--></ftl:template> </ftl:freemarker>
</smooks-resource-list>說明此配置文件的作用是通過內(nèi)置freemaker模板將input-message.xml中的格式進(jìn)行轉(zhuǎn)換。結(jié)果請(qǐng)對(duì)照下面out.xml。
③.通過如下程序可讀取輸入報(bào)文input-message.xml和配置文件smooks-config.xml,并產(chǎn)生輸出文件out.xml.
package example;import org.milyn.Smooks;
import org.milyn.SmooksException;
import org.milyn.io.StreamUtils;
import org.xml.sax.SAXException;import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import java.io.*;/*** smooks轉(zhuǎn)換類* @author zhangzheng*/
public class Main {//讀入輸入報(bào)文private static byte[] messageIn = readInputMessage();/*** 主方法*/public static void main(String[] args) throws IOException, SAXException, SmooksException {String messageOut=Main.runSmooks(); //調(diào)用smooks轉(zhuǎn)換方法System.out.println(messageOut); //打印輸出結(jié)果StreamUtils.writeFile(new File("out.xml"), messageOut.getBytes()); //將輸出報(bào)文寫出到文件out.xml
}/*** 根據(jù)配置文件輸入報(bào)文的byte[]轉(zhuǎn)化為輸出報(bào)文的String* 利用smooks進(jìn)行轉(zhuǎn)化*/protected static String runSmooks() throws IOException, SAXException, SmooksException {// 讀取配置文件smooks-config.xmlSmooks smooks = new Smooks("smooks-config.xml");CharArrayWriter outputWriter = new CharArrayWriter(); //存入smooks的轉(zhuǎn)化結(jié)果存入CharArrayWriter的對(duì)象,該類繼承java.io.writertry {//調(diào)用smooks.filterSource方法,進(jìn)行smooks轉(zhuǎn)化。smooks.filterSource(new StreamSource(new ByteArrayInputStream(messageIn)), new StreamResult(outputWriter));return outputWriter.toString();} finally {smooks.close();}}private static byte[] readInputMessage() {try {return StreamUtils.readStream(new FileInputStream("input-message.xml"));} catch (IOException e) {e.printStackTrace();return "<no-message/>".getBytes();}}
}④.輸出的報(bào)文out.xml:<?xml version="1.0" encoding="GBK"?>
<salesorder type="REQUEST" version="1.0"> <details> <orderid>332</orderid> <customer> <id>123</id> <name>Joe</name> </customer> </details> <itemList> <item> <id>1</id> <productId>1</productId> <quantity>2</quantity> <price>8.80</price> </item><item> <id>2</id> <productId>2</productId> <quantity>3</quantity> <price>10.90</price> </item></itemList>
</salesorder>2. Csv To Xml
Csv轉(zhuǎn)化成xml的配置也有兩種(xsl和freemaker),由于freemaker模板易于控制,下面介紹freemaker方法。
工程名:MyCsvToXml
①.需要轉(zhuǎn)換的報(bào)文:文件名在程序中定為input-message.csv
說明cvs文件一般是用","分隔,如果分隔符為"|"符號(hào),需要在配置文件smooks-config.xml <csv:reader> 中增加一個(gè)屬性separator="|",對(duì)于其他分隔符號(hào)同樣適用。
SYN,100006,eies,eies,19002020102,24,0187,0187,200804060001,2009-08-06,12:30:30,2020,110880829200904000016,②.配置轉(zhuǎn)化的配置文件,在程序中名為smooks-config.xml:
<?xml version="1.0"?>
<smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd"xmlns:csv="http://www.milyn.org/xsd/smooks/csv-1.2.xsd"xmlns:core="http://www.milyn.org/xsd/smooks/smooks-core-1.3.xsd"xmlns:ftl="http://www.milyn.org/xsd/smooks/freemarker-1.1.xsd"><csv:reader fields="SVCTYPE,SVCCODE,SVCNAME,SVCSEQNO,
EXTENTERPCODE,EXTPROVCODE,EXTAREACODE,EXTSITECODE,EXTSEQUENCENO,TRANSDATE,TRANSTIME,EXTOPERATORCODE,C_PLY_NO,C_PASSWORD" rootElementName="PACKET" recordElementName="PACKET"><csv:singleBinding beanId="PACKET" class="java.util.HashMap"/></csv:reader><!-- Use the SAX filter - more memory efficient and handle huge streams. --><core:filterSettings type="SAX" /><!-- Apply a FreeMarker template to each CSV record, generating a different XML structure based on the gender value... --><ftl:freemarker applyOnElement="PACKET"><ftl:template><!--<PACKET type="REQUEST" version="1.0"> <HEAD><SVCTYPE>${PACKET.SVCTYPE}</SVCTYPE><SVCCODE>${PACKET.SVCCODE}</SVCCODE><SVCNAME>${PACKET.SVCNAME}</SVCNAME><SVCSEQNO>${PACKET.SVCSEQNO}</SVCSEQNO><SVCSTATUS>000000</SVCSTATUS><SVCMESSAGE></SVCMESSAGE><SVCDETAIL>QueryPolicyByProposalNoService</SVCDETAIL></HEAD><THIRD><EXTENTERPCODE>${PACKET.EXTENTERPCODE}</EXTENTERPCODE><EXTPROVCODE>${PACKET.EXTPROVCODE}</EXTPROVCODE><EXTAREACODE>${PACKET.EXTAREACODE}</EXTAREACODE><EXTSITECODE>${PACKET.EXTSITECODE}</EXTSITECODE><EXTSEQUENCENO>${PACKET.EXTSEQUENCENO}</EXTSEQUENCENO><TRANSDATE>${PACKET.TRANSDATE}</TRANSDATE><TRANSTIME>${PACKET.TRANSTIME}</TRANSTIME><EXTOPERATORCODE>${PACKET.EXTOPERATORCODE}</EXTOPERATORCODE></THIRD> <BASE_LIST><BASE_DATA><C_PLY_NO>${PACKET.C_PLY_NO}</C_PLY_NO><C_PASSWORD>${PACKET.C_PASSWORD}</C_PASSWORD></BASE_DATA></BASE_LIST>
</PACKET>--></ftl:template><ftl:use><ftl:inline directive="replace"/></ftl:use></ftl:freemarker></smooks-resource-list>說明此配置文件的總用是將input-message.csv中的信息加上相應(yīng)的標(biāo)簽頭,轉(zhuǎn)換成xml,并在生成的xml 中加入csv中缺失的標(biāo)簽。結(jié)果請(qǐng)對(duì)照下面out.xml。
③.通過如下程序可讀取輸入報(bào)文input-message.csv和配置文件smooks-config.xml,運(yùn)行程序,產(chǎn)生輸出文件out.xml.
package example;import org.milyn.Smooks;
import org.milyn.SmooksException;
import org.milyn.io.StreamUtils;
import org.xml.sax.SAXException;import javax.xml.transform.stream.StreamSource;
import javax.xml.transform.stream.StreamResult;
import java.io.*;/*** csvToXMl* @author zhangzheng*/
public class Main {//讀入輸入報(bào)文private static byte[] messageIn = readInputMessage();/*** 主方法*/public static void main(String[] args) throws IOException, SAXException, SmooksException {String messageOut = Main.runSmooksTransform();StreamUtils.writeFile(new File("out.xml"), messageOut.getBytes());}/*** 根據(jù)配置文件輸入報(bào)文的byte[]轉(zhuǎn)化為輸出報(bào)文的String* 利用smooks進(jìn)行轉(zhuǎn)化*/protected static String runSmooksTransform() throws IOException, SAXException, SmooksException {Smooks smooks = new Smooks("smooks-config.xml");try {StringWriter writer = new StringWriter();smooks.filterSource(new StreamSource(new InputStreamReader(new ByteArrayInputStream(messageIn), "UTF-8")), new StreamResult(writer));return writer.toString();} finally {smooks.close();}}/*** 讀入輸入報(bào)文* @return 輸入報(bào)文的byte[]*/private static byte[] readInputMessage() {try {return StreamUtils.readStream(new FileInputStream("input-message.csv"));} catch (IOException e) {e.printStackTrace();return "<no-message/>".getBytes();}}
}④.輸出的報(bào)文out.xml:<PACKET type="REQUEST" version="1.0"> <HEAD><SVCTYPE>SYN</SVCTYPE><SVCCODE>100006</SVCCODE><SVCNAME>eies</SVCNAME><SVCSEQNO>eies</SVCSEQNO><SVCSTATUS>000000</SVCSTATUS><SVCMESSAGE></SVCMESSAGE><SVCDETAIL>QueryPolicyByProposalNoService</SVCDETAIL></HEAD> <THIRD><EXTENTERPCODE>19002020102</EXTENTERPCODE><EXTPROVCODE>24</EXTPROVCODE><EXTAREACODE>0187</EXTAREACODE><EXTSITECODE>0187</EXTSITECODE><EXTSEQUENCENO>200804060001</EXTSEQUENCENO><TRANSDATE>2009-08-06</TRANSDATE><TRANSTIME>12:30:30</TRANSTIME><EXTOPERATORCODE>2020</EXTOPERATORCODE></THIRD> <BASE_LIST><BASE_DATA><C_PLY_NO>110880829200904000016</C_PLY_NO><C_PASSWORD></C_PASSWORD></BASE_DATA></BASE_LIST>
</PACKET>3. 拓展
Smooks 還可以進(jìn)行Json, EDI 等常用數(shù)據(jù)格式的文件轉(zhuǎn)化。具體方法請(qǐng)參加從smooks官網(wǎng)下載下來的smooks-1.4文件夾中/docs/SmooksUserGuide_v1.4.html的說明。具體的程序可以參加\examples下的例子。
?
轉(zhuǎn)載于:https://www.cnblogs.com/svennee/p/4078883.html
總結(jié)
以上是生活随笔為你收集整理的Smooks转换设计的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【转】 代理模式
- 下一篇: 支持java虚拟主机_为何缺乏支持Jav