XSLT Mapping从字符串数据中读取并创建相应的xml标记

时间:2017-02-24 13:49:19

标签: xml xslt

有关如何通过XSLT映射实现此目的的任何建议

源XML:

<pay:MT_Source xmlns:pay='http://company.com/PaymentMethod' xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'>
<data contentLength='1796' contentType='text/csv;charset=UTF-8'>Company Account,Merchant Account,Reserved
Data1,Data2,Data3
Data4,Data5,Data6
Data7,Data8,Data9
</data>
</pay:MT_Source>

目标XML:

<pay:MT_Source xmlns:pay='http://company.com/PaymentMethod' xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'>
   <data contentLength='1796' contentType='text/csv;charset=UTF-8'>
   <record>
   <Company Account>Data1</Company Account>
   <Merchant Account>Data2</Merchant Account>
   <Reserved>Data3<Reserved>
   </record>
   <record>
   <Company Account>Data4</Company Account>
   <Merchant Account>Data5</Merchant Account>
   <Reserved>Data6<Reserved>
   </record>
   <record>
   <Company Account>Data7</Company Account>
   <Merchant Account>Data8</Merchant Account>
   <Reserved>Data9<Reserved>
   </record>
   </data>
</pay:MT_Source>

请注意,有&#39; &#x0a;&#39;在每一行的末尾而不是逗号。

1 个答案:

答案 0 :(得分:0)

这是一个XSLT 2.0选项。

注意:Company AccountMerchant Account不是有效的元素名称。我删除了空格以使它们有效。您还可以通过测试值castable as xs:QName来检查该值是否为有效名称。

XML输入

<pay:MT_Source xmlns:pay='http://company.com/PaymentMethod' xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'>
<data contentLength='1796' contentType='text/csv;charset=UTF-8'>Company Account,Merchant Account,Reserved
Data1,Data2,Data3
Data4,Data5,Data6
Data7,Data8,Data9
</data>
</pay:MT_Source>

XSLT 2.0

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

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

  <xsl:template match="data[tokenize(@contentType,';') = 'text/csv']">
    <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <xsl:variable name="header-tokens" as="xs:string*">
        <xsl:analyze-string select="." regex="\r\n?|\n">
          <xsl:non-matching-substring>
            <xsl:if test="position()=1">
              <xsl:sequence select="tokenize(replace(.,'\s',''),',')"/>
            </xsl:if>
          </xsl:non-matching-substring>
        </xsl:analyze-string>
      </xsl:variable>
      <xsl:analyze-string select="." regex="\r\n?|\n">
        <xsl:non-matching-substring>
          <xsl:if test="not(position()=1)">
            <record>
              <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>
            </record>
          </xsl:if>
        </xsl:non-matching-substring>
      </xsl:analyze-string>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

<强>输出

<pay:MT_Source xmlns:pay="http://company.com/PaymentMethod"
               xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <data contentLength="1796" contentType="text/csv;charset=UTF-8">
      <record>
         <CompanyAccount>Data1</CompanyAccount>
         <MerchantAccount>Data2</MerchantAccount>
         <Reserved>Data3</Reserved>
      </record>
      <record>
         <CompanyAccount>Data4</CompanyAccount>
         <MerchantAccount>Data5</MerchantAccount>
         <Reserved>Data6</Reserved>
      </record>
      <record>
         <CompanyAccount>Data7</CompanyAccount>
         <MerchantAccount>Data8</MerchantAccount>
         <Reserved>Data9</Reserved>
      </record>
   </data>
</pay:MT_Source>

这里的工作示例:http://xsltransform.net/6rewNyU

此外,如果csv中可能引用了带逗号的值,则可以将record部分更改为:

<record>
  <xsl:analyze-string select="." 
    regex="&quot;([^&quot;]*)&quot;,?|([^,]+),?">
    <xsl:matching-substring>
      <xsl:variable name="pos" select="position()"/>
      <xsl:element name="{$header-tokens[$pos]}">
        <xsl:value-of 
          select="normalize-space(concat(regex-group(1),regex-group(2)))"/>
      </xsl:element>
    </xsl:matching-substring>
  </xsl:analyze-string>
</record>

更新示例:http://xsltransform.net/6rewNyU/1