Smooks转换设计
生活随笔
收集整理的這篇文章主要介紹了
Smooks转换设计
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Smooks轉換設計
背景
不同的合作銀行對應的外部接口是不一樣的,我們需要把外部這些變化不定的接口格式,轉換為我們銀保通系統可以識別的內部接口.Smooks可以很好的解決這一問題.并且,當合作銀行的接口隨著業務的變化而發生變化時,smooks只需要通過變更轉換模板,就可以實現對變化后接口的支持。
Smooks框架可以在smooks的官網www.smooks.org (需要FQ軟)下載。本文smooks的版本是smooks-1.4。在其lib文件夾中是所需要的jar包。將所有jar包導入你的工程中,就能使用smooks進行報文解析了。
現在說明下面兩種種轉換:XmlToXml,CsvToXml.
1. Xml To Xml
說明xml轉換為xml在smooks的配置中有兩種方式,一種是通過xsl模板控制,一種是通過freemaker模板控制。其中后者比較靈活,格式容易控制,推薦使用后者。
1.1 use xsl Templating
工程名為MyXmlToXml①.需要轉換的報文:文件名在程序中定為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>②.配置轉化的配置文件,在程序中名為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>說明此配置文件的作用是通過內置xsl的配置將input-message.xml中的一些標簽名替換掉,例如:
將<TRANSTYPE>替換成</SVCTYPE>,新增加一些丟失的標簽例如<SVCDETAIL>QueryPolicyByProposalNoService</SVCDETAIL>,并且將<BODY> 標簽下的內容改為一個list類型的標簽。結果請對照下面out.xml。
③.通過如下程序可讀取輸入報文input-message.xml和配置文件smooks-config.xml,并產生輸出文件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 {//讀入輸入報文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()); //將輸出報文寫出到文件out.xml
}/*** 根據配置文件輸入報文的byte[]轉化為輸出報文的String* 利用smooks進行轉化*/protected static String runSmooksTransform() throws IOException, SAXException, SmooksException {// 讀取配置文件smooks-config.xmlSmooks smooks = new Smooks("smooks-config.xml");try {CharArrayWriter outputWriter = new CharArrayWriter(); //存入smooks的轉化結果存入CharArrayWriter的對象,該類繼承java.io.writer//調用smooks.filterSource方法,進行smooks轉化。smooks.filterSource(new StreamSource(new ByteArrayInputStream(messageIn)), new StreamResult(outputWriter));return outputWriter.toString(); //將轉化結果轉化為字符串} finally {smooks.close();}}/*** 讀入輸入報文* @return 輸入報文的byte[]*/private static byte[] readInputMessage() {try {return StreamUtils.readStream(new FileInputStream("input-message.xml"));} catch (IOException e) {e.printStackTrace();return "<no-message/>".getBytes();}}
}④.輸出的報文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①.需要轉換的報文:文件名在程序中定為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>②.配置轉化的配置文件,在程序中名為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>說明此配置文件的作用是通過內置freemaker模板將input-message.xml中的格式進行轉換。結果請對照下面out.xml。
③.通過如下程序可讀取輸入報文input-message.xml和配置文件smooks-config.xml,并產生輸出文件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轉換類* @author zhangzheng*/
public class Main {//讀入輸入報文private static byte[] messageIn = readInputMessage();/*** 主方法*/public static void main(String[] args) throws IOException, SAXException, SmooksException {String messageOut=Main.runSmooks(); //調用smooks轉換方法System.out.println(messageOut); //打印輸出結果StreamUtils.writeFile(new File("out.xml"), messageOut.getBytes()); //將輸出報文寫出到文件out.xml
}/*** 根據配置文件輸入報文的byte[]轉化為輸出報文的String* 利用smooks進行轉化*/protected static String runSmooks() throws IOException, SAXException, SmooksException {// 讀取配置文件smooks-config.xmlSmooks smooks = new Smooks("smooks-config.xml");CharArrayWriter outputWriter = new CharArrayWriter(); //存入smooks的轉化結果存入CharArrayWriter的對象,該類繼承java.io.writertry {//調用smooks.filterSource方法,進行smooks轉化。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();}}
}④.輸出的報文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轉化成xml的配置也有兩種(xsl和freemaker),由于freemaker模板易于控制,下面介紹freemaker方法。
工程名:MyCsvToXml
①.需要轉換的報文:文件名在程序中定為input-message.csv
說明cvs文件一般是用","分隔,如果分隔符為"|"符號,需要在配置文件smooks-config.xml <csv:reader> 中增加一個屬性separator="|",對于其他分隔符號同樣適用。
SYN,100006,eies,eies,19002020102,24,0187,0187,200804060001,2009-08-06,12:30:30,2020,110880829200904000016,②.配置轉化的配置文件,在程序中名為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中的信息加上相應的標簽頭,轉換成xml,并在生成的xml 中加入csv中缺失的標簽。結果請對照下面out.xml。
③.通過如下程序可讀取輸入報文input-message.csv和配置文件smooks-config.xml,運行程序,產生輸出文件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 {//讀入輸入報文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());}/*** 根據配置文件輸入報文的byte[]轉化為輸出報文的String* 利用smooks進行轉化*/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();}}/*** 讀入輸入報文* @return 輸入報文的byte[]*/private static byte[] readInputMessage() {try {return StreamUtils.readStream(new FileInputStream("input-message.csv"));} catch (IOException e) {e.printStackTrace();return "<no-message/>".getBytes();}}
}④.輸出的報文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 還可以進行Json, EDI 等常用數據格式的文件轉化。具體方法請參加從smooks官網下載下來的smooks-1.4文件夾中/docs/SmooksUserGuide_v1.4.html的說明。具體的程序可以參加\examples下的例子。
?
轉載于:https://www.cnblogs.com/svennee/p/4078883.html
總結
以上是生活随笔為你收集整理的Smooks转换设计的全部內容,希望文章能夠幫你解決所遇到的問題。