2017-11-06 1 views
0

XSLT 2.0 (Saxon 프로세서)으로 작업 중이며 xml을 다른 것으로 변환하려고합니다. 샘플 입력 XML의 모양은 다음과 같습니다.조건부로 XSLT 2.0을 사용하여 XML 태그 값 바꾸기

<Customer> 
    <Name>{{customer_name}}</Name> 
    <Transaction>{{customer_transaction}}</Transaction> 
    <Id>134</Id> 
</Customer> 

각 XML 태그의 값을 확인하고 해당 필드 이름이 예 : customer_name 또는 customer_transaction? 그것이 필드 이름이라면 나는 외부 csv 파일에서 그 값을 찾고 그 값을 대체 할 필요가있다.

지금까지 프로그래밍 한 xsl 템플릿은 다음과 같습니다. 누군가 그것을 완료하는데 나를 도울 수 있습니까?

<xsl:stylesheet 
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
     xmlns:fn="fn" 
     xmlns:xs="http://www.w3.org/2001/XMLSchema" 
     version="2.0" exclude-result-prefixes="xs fn"> 

<xsl:output method="xml" omit-xml-declaration="yes"/> 

    <xsl:param name="csv-uri" 
       select="'file:///E:/data.csv'"/> 

    <xsl:variable name="csv" select="unparsed-text($csv-uri)"/> 


    <!-- Identity template : copy all text nodes, elements and attributes --> 
    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:function name="fn:getTokens" as="xs:string+"> 
     <xsl:param name="str" as="xs:string"/> 
     <xsl:analyze-string select="concat($str, ',')" regex='(("[^"]*")+|[^,]*),'> 
      <xsl:matching-substring> 
       <xsl:sequence select='replace(regex-group(1), "^""|""$|("")""", "$1")'/> 
      </xsl:matching-substring> 
     </xsl:analyze-string> 
    </xsl:function> 

    <xsl:variable name="lines" select="tokenize($csv, '\r\n')" as="xs:string+"/> 
    <xsl:variable name="headerColNames" select="fn:getTokens($lines[1])" as="xs:string+"/> 

    <xsl:template match="*/text()[starts-with(.,'{{')]"> 
     <!-- add more code here --> 
    </xsl:template> 

</xsl:stylesheet> 

data.csv는 아래의 데이터

customer_name, customer_transaction 
abc, T1 
xyz, T2 

가있는 경우 출력 XML 우리는 첫 번째 레코드에 대해 우려하고

<Customer> 
    <Name>abc</Name> 
    <Transaction>T1</Transaction> 
    <Id>134</Id> 
</Customer> 

주처럼 보일 것입니다.

감사합니다.

답변

0

먼저 CSV를 XML로 변환 한 다음 일치시키고 선택하는 것으로 생각합니다. 여기서는 XSLT 3 솔루션을 사용합니다 (코드 라인은 XSLT 2로 변환 할 수 있지만 Saxon 9.8은 XSLT 3을 실행합니다) :

<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">test2017110601.txt</xsl:param> 

    <xsl:param name="field-pattern" as="xs:string">\{\{.+\}\}</xsl:param> 

    <xsl:param name="repl-pattern" as="xs:string">^\{\{|\}\}$</xsl:param> 

    <xsl:param name="sep-pattern" as="xs:string">,\s*</xsl:param> 

    <xsl:param name="csv-lines" as="xs:string*" select="tokenize(unparsed-text($csv-uri), '\r?\n')"/> 
    <xsl:variable name="col-names" as="xs:string*" select="tokenize($csv-lines[1], $sep-pattern)"/> 

    <xsl:variable name="csv-doc"> 
     <xsl:for-each select="$csv-lines[position() gt 1][normalize-space()]"> 
      <row> 
       <xsl:variable name="cols" as="xs:string*" select="tokenize(., ',\s*')"/> 
       <xsl:for-each select="$col-names"> 
        <xsl:element name="{.}"> 
         <xsl:variable name="p" as="xs:integer" select="position()"/> 
         <xsl:value-of select="$cols[$p]"/> 
        </xsl:element> 
       </xsl:for-each> 
      </row> 
     </xsl:for-each> 
    </xsl:variable> 

    <xsl:key name="fields" match="row/*" use="local-name()"/> 

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

    <xsl:template match="*[not(*) and matches(., $field-pattern)]"> 
     <xsl:copy> 
      <xsl:value-of select="key('fields', replace(., $repl-pattern, ''), $csv-doc)[1]"/> 
     </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 
: 여기
<?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" 
    xmlns:math="http://www.w3.org/2005/xpath-functions/math" 
    exclude-result-prefixes="xs math" 
    expand-text="yes" 
    version="3.0"> 

    <xsl:param name="csv-uri" as="xs:string">test2017110601.txt</xsl:param> 

    <xsl:param name="field-pattern" as="xs:string" expand-text="no">\{\{.+\}\}</xsl:param> 

    <xsl:param name="repl-pattern" as="xs:string" expand-text="no">^\{\{|\}\}$</xsl:param> 

    <xsl:param name="sep-pattern" as="xs:string">,\s*</xsl:param> 

    <xsl:param name="csv-lines" as="xs:string*" select="unparsed-text-lines($csv-uri)"/> 
    <xsl:variable name="col-names" as="xs:string*" select="tokenize(head($csv-lines), $sep-pattern)"/> 

    <xsl:variable name="csv-doc"> 
     <xsl:apply-templates select="tail($csv-lines)[normalize-space()]" mode="lines"/> 
    </xsl:variable> 

    <xsl:key name="fields" match="row/*" use="local-name()"/> 

    <xsl:mode on-no-match="shallow-copy"/> 

    <xsl:template match=".[. instance of xs:string]" mode="lines"> 
     <row> 
      <xsl:variable name="cols" as="xs:string*" select="tokenize(., ',\s*')"/> 
      <xsl:for-each select="$col-names"> 
       <xsl:element name="{.}">{let $p := position() return $cols[$p]}</xsl:element> 
      </xsl:for-each> 
     </row> 
    </xsl:template> 

    <xsl:template match="*[not(*) and matches(., $field-pattern)]"> 
     <xsl:copy> 
      <xsl:value-of select="key('fields', replace(., $repl-pattern, ''), $csv-doc)[1]"/> 
     </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

는 XSLT 2 버전
관련 문제