使用xslt将csv转换为xml

时间:2019-04-16 10:27:49

标签: xml xslt

我不是开发人员,但是我在技术行业工作,并且具有xslt的基本知识。 在下面的情况下,我将非常感谢您的帮助。也许一旦有了一个例子,我就可以推断出其他用例。

在csv中,我具有以下列: 名称 位置 工作1 工作2 职位3

工作1具有其他属性,例如开始时间,结束时间和薪酬 工作2有轮班,奖金 职位3有销售,操作

csv中的示例值:

Name, Location,Job_Type,Start_time, End_time,Pay, Shift, Bonus,Sales, Ops
john, london,Job_1,800,1900,400, , , , ,
john, london,Job_2, , , ,evening,20000, , , 
john, london,Job_3, , , , , , 200,500

如何确保csv中的这3个单独的行可以转换为一个xml结构:

<name>john</name>
  <location>london</location>
    <Job_1>
      <Start_time>800</Start_time>
      <End_time>1900</End_time>
      <Pay>400</Pay>
    </Job_1>
    <Job_2>
      <Shift>evening</Shift>
      <Bonus>20000</Bonus>
    </Job_2>
    <Job_3>
      <Sales>200</Sales>
      <Ops>500</Ops>
    </Job_3>

我当时正在考虑设置一个变量,该变量首先是名称和位置。 然后为每个做一个。不知道如果每个元素的名称都是this.name,我将如何创建一个语句。

我非常感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

使用XSLT 3(受开源Saxon 9.8和更高版本的HE软件以及Altova 2017和更高版本的支持),您可以使用CSV将输入字符串分解为一系列字符串数组,然后在第一个字符串数组中进行分组数组项如下:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:array="http://www.w3.org/2005/xpath-functions/array"
    exclude-result-prefixes="xs array"
    version="3.0">

  <xsl:param name="csv-input" as="xs:string">Name, Location,Job_Type,Start_time, End_time,Pay, Shift, Bonus,Sales, Ops
john, london,Job_1,800,1900,400, , , , ,
john, london,Job_2, , , ,evening,20000, , , 
john, london,Job_3, , , , , , 200,500</xsl:param>

  <xsl:param name="lines" as="xs:string*" select="tokenize($csv-input, '\r?\n')"/>

  <xsl:param name="headers" as="xs:string*" select="tokenize(head($lines), '\s*,\s*')"/>

  <xsl:param name="data" as="array(xs:string)*" select="tail($lines)!array{ tokenize(., '\s*,\s*') }"/>

  <xsl:output method="xml" indent="yes" />

  <xsl:template match="/" name="xsl:initial-template" expand-text="yes">
      <root>
          <xsl:for-each-group select="$data" group-by=".(1)">
              <record>
                  <xsl:for-each select="subsequence($headers, 1, 2)">
                      <xsl:element name="{.}">{head(current-group())(position())}</xsl:element>
                  </xsl:for-each>
                  <xsl:for-each select="current-group()">
                      <xsl:element name="{.(3)}">
                          <xsl:variable name="values" select="."/>
                          <xsl:for-each select="(4 to count($headers))">
                              <xsl:if test="normalize-space($values(position() + 3))">
                                <xsl:element name="{$headers[current()]}">{$values(position() + 3)}</xsl:element>
                              </xsl:if>
                          </xsl:for-each>
                      </xsl:element>
                  </xsl:for-each>
              </record>
          </xsl:for-each-group>
      </root>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/3NJ38Zn/2

对于示例的自包含性,其中的CSV数据作为字符串参数传入,但是您当然可以使用<xsl:param name="csv-input" as="xs:string" select="unparsed-text('file.csv')"/>来从CSV文件中加载数据。

当然,XSLT 3并不是必需的,而使用XSLT 2,通常的方法是将CSV转换为XML,然后根据需要进行分组。