2017-06-23 95 views
0

我在嘗試將逗號分隔列表轉換爲具有分層結構的XML文件。爲此,我單獨使用XSLT,最好使用一種轉換。有一個前面的例子是相似的,但它並沒有深入到創建子元素的深處,在我所知的這種轉換過程中,我發現這是一個常見的問題,沒有一個明確的答案。使用一個XSL轉換將CSV文件轉換爲分層XML

類似的實施例: XSLT 2.0 to convert CSV to XML format

CSV例

ClaimRef,HandlerRef,ClaimType,Date,Area,SettleDate,ClaimStatus,ClaimantName 
1,1/1,Liability,08-12-2013,US,23-05-2014,Closed,Mark 
2,1/2,Liability,08-10-2013,UK,23-02-2014,Closed,John 

希望的XML輸出格式(如果是這種不同,因爲它包含的子元素)

<Claims> 
<Claim> 
    <ClaimRef></ClaimRef> 
    <HandlerRef></HandlerRef> 
    <ClaimType></ClaimType> 
    <Date></Date> 
    <Area></Area> 
    <SettleDate></SettleDate> 
    <ImportantDevision> 
     <ClaimStatus></ClaimStatus> 
     <ClaimantName></ClaimantName> 
    </ImportantDivision> 
</Claim> 
</Claims> 

工作XSLT 2.0版無子元素

<xsl:param name="inputCsv"/> 
<xsl:template match="/" name="csv2xml"> 
    <Claims> 
     <xsl:variable name="csv" select="unparsed-text($csv-uri, $csv-encoding)"/> 
       <!--Get Header--> 
       <xsl:variable name="header-tokens" as="xs:string*"> 
        <xsl:analyze-string select="$csv" regex="\r\n?|\n"> 
         <xsl:non-matching-substring> 
          <xsl:if test="position()=1"> 
           <xsl:copy-of select="tokenize(.,',')"/>           
          </xsl:if> 
         </xsl:non-matching-substring> 
        </xsl:analyze-string> 
       </xsl:variable>      
       <xsl:analyze-string select="$csv" regex="\r\n?|\n"> 
        <xsl:non-matching-substring> 
         <xsl:if test="not(position()=1)"> 
          <Claim> 
           <xsl:for-each select="tokenize(.,',')"> 
            <xsl:variable name="pos" select="position()"/> 
            <xsl:element name="{$header-tokens[$pos]}"> 
             <xsl:value-of select="."/> 
            </xsl:element> 
           </xsl:for-each> 
          </Claim> 
         </xsl:if> 
        </xsl:non-matching-substring> 
       </xsl:analyze-string> 
    </Claims> 
</xsl:template> 

我會再有,爲了欺騙XSL轉換我的CSV文件虛擬XML文件。 也許更好的問題是如何在標籤名稱,屬性,ID等被創建之前使用XSLT來區分各個分區?

+0

不知道到底你的問題是什麼。您的樣式表將同一行中的所有單元格對待。如果你想把它們中的一些放在一個包裝元素中,你必須告訴樣式表哪些 - 不管是按名稱還是按位置。這些信息不能從輸入中推斷出來。 –

+0

這裏的文章http://www.saxonica.com/papers/ideadb-1.1/mhk-paper.xml討論了一個類似的問題,它可能會給你一些想法。請注意,對於XSLT 2.0,不需要具有XML源文檔:您可以在命名模板中啓動處理。 –

回答

0

您沒有真正解釋嵌套元素的標準,但正如在評論中已經指出的那樣,您可以首先以任何方式轉換您創建的平面XML。下面假設你只是想先從名字Claim窩相鄰元素:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0"> 

    <xsl:param name="csv-uri" as="xs:string" select="'test2017062301.txt'"/> 
    <xsl:param name="csv-encoding" as="xs:string" select="'Windows-1252'"/> 

    <xsl:output indent="yes"/> 

    <xsl:template match="@* | node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@* | node()"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="/" name="csv2xml"> 
     <Claims> 
      <xsl:variable name="csv" select="unparsed-text($csv-uri, $csv-encoding)"/> 
      <xsl:variable name="flat-xml"> 
       <!--Get Header--> 
       <xsl:variable name="header-tokens" as="xs:string*"> 
        <xsl:analyze-string select="$csv" regex="\r\n?|\n"> 
         <xsl:non-matching-substring> 
          <xsl:if test="position() = 1"> 
           <xsl:copy-of select="tokenize(., ',')"/> 
          </xsl:if> 
         </xsl:non-matching-substring> 
        </xsl:analyze-string> 
       </xsl:variable> 
       <xsl:analyze-string select="$csv" regex="\r\n?|\n"> 
        <xsl:non-matching-substring> 
         <xsl:if test="not(position() = 1)"> 
          <Claim> 
           <xsl:for-each select="tokenize(., ',')"> 
            <xsl:variable name="pos" select="position()"/> 
            <xsl:element name="{$header-tokens[$pos]}"> 
             <xsl:value-of select="."/> 
            </xsl:element> 
           </xsl:for-each> 
          </Claim> 
         </xsl:if> 
        </xsl:non-matching-substring> 
       </xsl:analyze-string> 
      </xsl:variable> 
      <xsl:apply-templates select="$flat-xml/*"/> 
     </Claims> 
    </xsl:template> 

    <xsl:template match="Claim"> 
     <xsl:copy> 
      <xsl:for-each-group select="*" group-adjacent="starts-with(local-name(), 'Claim')"> 
       <xsl:choose> 
        <xsl:when test="current-grouping-key() and current-group()[2]"> 
         <ClaimDivision> 
          <xsl:copy-of select="current-group()"/> 
         </ClaimDivision> 
        </xsl:when> 
        <xsl:otherwise> 
         <xsl:copy-of select="current-group()"/> 
        </xsl:otherwise> 
       </xsl:choose> 
      </xsl:for-each-group> 
     </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

結果爲您的樣品輸入則是

<?xml version="1.0" encoding="UTF-8"?> 
<Claims> 
    <Claim> 
     <ClaimRef>1</ClaimRef> 
     <HandlerRef>1/1</HandlerRef> 
     <ClaimType>Liability</ClaimType> 
     <Date>08-12-2013</Date> 
     <Area>US</Area> 
     <SettleDate>23-05-2014</SettleDate> 
     <ClaimDivision> 
     <ClaimStatus>Closed</ClaimStatus> 
     <ClaimantName>Mark</ClaimantName> 
     </ClaimDivision> 
    </Claim> 
    <Claim> 
     <ClaimRef>2</ClaimRef> 
     <HandlerRef>1/2</HandlerRef> 
     <ClaimType>Liability</ClaimType> 
     <Date>08-10-2013</Date> 
     <Area>UK</Area> 
     <SettleDate>23-02-2014</SettleDate> 
     <ClaimDivision> 
     <ClaimStatus>Closed</ClaimStatus> 
     <ClaimantName>John</ClaimantName> 
     </ClaimDivision> 
    </Claim> 
</Claims>