XSLT2.0 從外部讀取資訊並分析生成對應檔案.採用xsl:for-each-group進行排序輸出
阿新 • • 發佈:2019-02-19
解析器:Saxon
XSLT2.0相對於XSLT1.0增加了unparsed-text() collection() 函式.並且支援xsl:for-each-group來對資料進行排序.
以下程式碼主要實現的過程是:
A.使用unparsed-text()讀取外部檔案資訊.
B.使用xsl:result-document生成對應資訊的XML檔案.(使用XSLT2.0 tokenize()函式拆解捕獲資訊)
C.合併多個XML檔案.主要使用到XSLT2.0 collection()函式過濾當前資料夾中的XML檔案.
D.使用for-each-group對合並檔案中的物件進行排序重新輸出.
模擬emoplyees資訊儲存於empolyees.csv檔案中.(Format firstname,lastname,jobTitle,department)
Joe, Fawcett, Developer, IT Max, Bialystock, CEO, Management Phineas, Barnum, Head of Sales, Sales and Marketing Leo, Bloom, Auditor, Accounts Danny, Ayers, Developer, IT Carmen, Ghia, PA to the VP of Products, Management Ulla, Anderson, Head of Promotions, Sales and Marketing Grace, Hopper, Developer, IT Bob, Cratchit, Bookkeeper, Accounts Charles, Babbage, Head of Infrastructure, IT Roger, De Bris, VP of Products, Management Willy, Loman, Salesman, Sales and Marketing Franz, Liebkind, Developer, IT Luca, Pacioli, Accountant, Accounts Lorenzo, St. DuBois, Project Manager, IT
A.B.C三步對應的XSLT檔案如下:BuildXMLDataFromExtendFile.xslt
可在XSLT檔案中設定原始檔路徑及目標合併檔案路徑.
該XSLT檔案中定義了過濾標籤內容空格函式myFunction:removeSpace
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:myData="http://www.ricky.com/myData" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:myFunction="http://www.ricky.com/myFunction" exclude-result-prefixes="myData myFunction xs"> <!-- content in empolyees.csv dataFormat: $firstName,$lastName,$jobTitle,$department Joe, Fawcett, Developer, IT Max, Bialystock, CEO, Management Phineas, Barnum, Head of Sales, Sales and Marketing Leo, Bloom, Auditor, Accounts Danny, Ayers, Developer, IT Carmen, Ghia, PA to the VP of Products, Management Ulla, Anderson, Head of Promotions, Sales and Marketing Grace, Hopper, Developer, IT Bob, Cratchit, Bookkeeper, Accounts Charles, Babbage, Head of Infrastructure, IT Roger, De Bris, VP of Products, Management Willy, Loman, Salesman, Sales and Marketing Franz, Liebkind, Developer, IT Luca, Pacioli, Accountant, Accounts Lorenzo, St. DuBois, Project Manager, IT --> <xsl:template name="main"> <xsl:variable name="fileLocation" select="myFunction:loadFilePath()" as="xs:string"/> <xsl:variable name="content" select="unparsed-text($fileLocation)" as="xs:string"/> <!-- the following code save the empolyee into the separate file --> <xsl:for-each select="tokenize($content,'\n')"> <xsl:call-template name="saveSeparateEmpolyee"> <xsl:with-param name="empolyeeInfo" select="."/> </xsl:call-template> </xsl:for-each> <!-- the following code save all separate empolyee files into empolyees.xml(location supply by myData:targetFileLocation) --> <xsl:call-template name="combineAllEmpolyees"> <xsl:with-param name="targetFile" select="myFunction:loadTargetFilePath()"/> </xsl:call-template> </xsl:template> <xsl:template name="saveSeparateEmpolyee"> <xsl:param name="empolyeeInfo" as="xs:string"/> <xsl:variable name="firstName" select="tokenize($empolyeeInfo,',\s*')[1]" as="xs:string"/> <xsl:variable name="lastName" select="tokenize($empolyeeInfo,',\s*')[2]" as="xs:string"/> <xsl:variable name="jobTitle" select="tokenize($empolyeeInfo,',\s*')[3]" as="xs:string"/> <xsl:variable name="department" select="tokenize($empolyeeInfo,',\s*')[4]" as="xs:string"/> <!-- the value of department with (CR (carriage return)) --> <xsl:result-document href="empolyee-{myFunction:removeSpace($firstName)}-{myFunction:removeSpace($lastName)}.xml"> <empolyee firstName="{$firstName}" lastName="{$lastName}" jobTitle="{$jobTitle}" department="{myFunction:replaceAll($department,' ','')}"/> </xsl:result-document> </xsl:template> <xsl:template name="combineAllEmpolyees"> <xsl:param name="targetFile" as="xs:string"/> <xsl:result-document href="{$targetFile}"> <allEmpolyees> <!-- load the empolyees information in separate-xml-file in current directory. format: empolyee-firstName-lastName.xml --> <xsl:for-each select="collection('?select=empolyee-*.xml')"> <xsl:copy-of select="."/> </xsl:for-each> </allEmpolyees> </xsl:result-document> </xsl:template> <!-- location to save all the empolyees information --> <myData:targetFileLocation> empolyees.xml </myData:targetFileLocation> <!-- location to read the information of all the empolyees--> <myData:extendsFilePath> empolyees.csv </myData:extendsFilePath> <xsl:function name="myFunction:loadTargetFilePath" as="xs:string"> <xsl:variable name="thisDocument" select="document('')"/> <xsl:variable name="result" select="myFunction:removeSpace($thisDocument/xsl:stylesheet/myData:targetFileLocation)" as="xs:string"/> <xsl:value-of select="$result"/> </xsl:function> <xsl:function name="myFunction:loadFilePath" as="xs:string"> <xsl:variable name="thisDocument" select="document('')"/> <xsl:variable name="fileLocation" select="myFunction:removeSpace($thisDocument/xsl:stylesheet/myData:extendsFilePath)" as="xs:string"/> <xsl:value-of select="$fileLocation"/> </xsl:function> <xsl:function name="myFunction:removeSpace" as="xs:string"> <xsl:param name="content" as="xs:string"/> <xsl:variable name="line" select="' '" as="xs:string"/> <xsl:variable name="tab" select="' '" as="xs:string"/> <xsl:variable name="space" select="' '" as="xs:string"/> <xsl:variable name="null" select="''" as="xs:string"/> <xsl:variable name="contentWithoutLine" select="myFunction:replaceAll($content,$line,$null)" as="xs:string"/> <xsl:variable name="contentWithoutTab" select="myFunction:replaceAll($contentWithoutLine,$tab,$null)" as="xs:string"/> <xsl:variable name="result" select="myFunction:replaceAll($contentWithoutTab,$space,$null)" as="xs:string"/> <xsl:value-of select="$result"/> </xsl:function> <xsl:function name="myFunction:replaceAll" as="xs:string"> <xsl:param name="content" as="xs:string"/> <xsl:param name="data" as="xs:string"/> <xsl:param name="replacement" as="xs:string"/> <xsl:choose> <xsl:when test="contains($content,$data)"> <xsl:variable name="before" select="substring-before($content,$data)" as="xs:string"/> <xsl:variable name="after" select="substring-after($content,$data)" as="xs:string"/> <xsl:variable name="newContent" select="concat($before,$replacement,$after)" as="xs:string"/> <xsl:value-of select="myFunction:replaceAll($newContent,$data,$replacement)" /> </xsl:when> <xsl:otherwise> <xsl:value-of select="$content" /> </xsl:otherwise> </xsl:choose> </xsl:function> </xsl:stylesheet>
執行命令: java net.sf.saxon.Transform -it:main -xsl:BuildXMLDataFromExtendFile.xslt 當前目錄下將生成對應每個empolyee的XML檔案及一個彙總檔案empolyees.xml(未排序)
接下來編寫empolyees.xlst檔案來對生成的未排序empolyees.xml進行重新排序
對應empolyees.xslt檔案內容如下:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:variable name="allEmpolyees" select="document('empolyees.xml')"/>
<xsl:template name="main">
<!-- Group the empolyees by @department. save as empolyees_group.xml -->
<xsl:result-document href="empolyees_group.xml">
<allEmpolyees>
<xsl:for-each-group select="$allEmpolyees/allEmpolyees/empolyee" group-by="@department">
<!-- sort by @deparment -->
<xsl:sort select="@department" data-type="text"/>
<department department="{current-grouping-key()}">
<xsl:comment>
The following show the empolyees in
<xsl:value-of select="current-grouping-key()"/>
</xsl:comment>
<xsl:apply-templates select="current-group()" mode="showDetail">
<!-- sort by @firstName + @lastName -->
<xsl:sort select="@firstName" data-type="text"/>
<xsl:sort select="@lastName" data-type="text"/>
</xsl:apply-templates>
</department>
</xsl:for-each-group>
</allEmpolyees>
</xsl:result-document>
</xsl:template>
<xsl:template match="empolyee" mode="showDetail">
<empolyee firstName="{@firstName}" lastName="{@lastName}" jobTitle="{@jobTitle}"/>
</xsl:template>
</xsl:stylesheet>
執行命令:java net.sf.saxon.Transform -it:main -xsl:empolyees.xslt
執行完畢後將在當前目錄下生成empolyees_group.xml檔案.
該檔案內容已經是對empolyees.xml進行排序處理後的結果.
empolyees_group.xml檔案內容如下:
<?xml version="1.0" encoding="UTF-8"?>
<allEmpolyees>
<department department="Accounts">
<!--
The following show the empolyees in
Accounts-->
<empolyee firstName="Bob" lastName="Cratchit" jobTitle="Bookkeeper"/>
<empolyee firstName="Leo" lastName="Bloom" jobTitle="Auditor"/>
<empolyee firstName="Luca" lastName="Pacioli" jobTitle="Accountant"/>
</department>
<department department="IT">
<!--
The following show the empolyees in
IT-->
<empolyee firstName="Charles" lastName="Babbage" jobTitle="Head of Infrastructure"/>
<empolyee firstName="Danny" lastName="Ayers" jobTitle="Developer"/>
<empolyee firstName="Franz" lastName="Liebkind" jobTitle="Developer"/>
<empolyee firstName="Grace" lastName="Hopper" jobTitle="Developer"/>
<empolyee firstName="Joe" lastName="Fawcett" jobTitle="Developer"/>
<empolyee firstName="Lorenzo" lastName="St. DuBois" jobTitle="Project Manager"/>
</department>
<department department="Management">
<!--
The following show the empolyees in
Management-->
<empolyee firstName="Carmen" lastName="Ghia" jobTitle="PA to the VP of Products"/>
<empolyee firstName="Max" lastName="Bialystock" jobTitle="CEO"/>
<empolyee firstName="Roger" lastName="De Bris" jobTitle="VP of Products"/>
</department>
<department department="Sales and Marketing">
<!--
The following show the empolyees in
Sales and Marketing-->
<empolyee firstName="Phineas" lastName="Barnum" jobTitle="Head of Sales"/>
<empolyee firstName="Ulla" lastName="Anderson" jobTitle="Head of Promotions"/>
<empolyee firstName="Willy" lastName="Loman" jobTitle="Salesman"/>
</department>
</allEmpolyees><strong>
</strong>