首页 > 解决方案 > 通过 XSLT 将 .txt 文件转换为 JSON

问题描述

我有以下 .txt 文件,其中包含示例数据,例如:

january,february,march
1,2,3

我使用以下代码首先将 .txt 文件转换为 XML,然后将其转换为 JSON。

XML 转换为我提供了以下输出:

<Sales>
   <Month>
      <january>1</january>
      <february>2</february>
      <march>3</march>
   </Month>
</Sales>

我正在尝试以以下格式以 JSON 格式输出此输出:

{
    "Month": [
        {
            "january": "1",
            "february": "2",
            "march": "3"
        }
}

我正在使用的代码如下,在 XML 部分之前都可以,但在 JSON 转换部分之前没有。

<?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:fn="http://www.w3.org/2005/xpath-functions"
    xmlns:exslt="http://exslt.org/common" extension-element-prefixes="exsl"
    xmlns:exsl="http://exslt.org/common" xmlns:fcn="http://www.re.com/2018/local-functions"
    exclude-result-prefixes="xs fn fcn exsl" version="3.0">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>
    <xsl:param name="csv-encoding" as="xs:string" select="'iso-8859-1'"/>
    <xsl:param name="csv-uri" as="xs:string" select="'/Users/user/Desktop/so.csv'"/>
    <xsl:template match="/" name="csv2xml">
        <Sales>
            <xsl:choose>
                <xsl:when test="unparsed-text-available($csv-uri, $csv-encoding)">
                    <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)">
                                <Month>
                                    <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>
                                </Month>
                            </xsl:if>
                        </xsl:non-matching-substring>
                    </xsl:analyze-string>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:variable name="error">
                        <xsl:text>Error reading "</xsl:text>
                        <xsl:value-of select="$csv-uri"/>
                        <xsl:text>" (encoding "</xsl:text>
                        <xsl:value-of select="$csv-encoding"/>
                        <xsl:text>").</xsl:text>
                    </xsl:variable>
                    <xsl:message><xsl:value-of select="$error"/></xsl:message>
                    <xsl:value-of select="$error"/>
                </xsl:otherwise>
            </xsl:choose>
        </Sales>
        <xsl:variable name="transformed-xml">
            <array xmlns="http://www.w3.org/2005/xpath-functions">
                <xsl:for-each select="Month">
                    <map>
                            <string key="id">
                                <xsl:value-of select="./january" />
                            </string>
                    </map>
                </xsl:for-each>
            </array>
        </xsl:variable>
        <xsl:value-of select="xml-to-json($transformed-xml, map {'indent': true()})" />
    </xsl:template>
</xsl:stylesheet>

标签: xmlxslt

解决方案


对于将您创建的 XML 转换为您可以提供的 XML 表示形式,xml-to-json我建议采用类似的方法

<?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:map="http://www.w3.org/2005/xpath-functions/map"
    xmlns="http://www.w3.org/2005/xpath-functions"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:output method="text"/>

  <xsl:template match="/">
      <xsl:variable name="xml-rep-of-json">
          <xsl:apply-templates/>
      </xsl:variable>
      <xsl:value-of select="xml-to-json($xml-rep-of-json, map { 'indent' : true() })"/>
  </xsl:template>

  <xsl:template match="Sales">
      <array>
          <xsl:apply-templates/>
      </array>
  </xsl:template>

  <xsl:template match="Month">
      <map>
          <xsl:apply-templates/>
      </map>
  </xsl:template>

  <xsl:template match="Month/*" expand-text="yes">
      <string key="{local-name()}">{.}</string>
  </xsl:template>

</xsl:stylesheet>

在 JSON 方面,它创建了一个顶级数组,其中包含未命名的 JSON 对象/映射,其中包含包含数据的命名字符串属性,例如

 [ 
    { "january" : "1",
      "february" : "2",
      "march" : "3" },

    { "january" : "1",
      "february" : "2",
      "march" : "3" } ]

https://xsltfiddle.liberty-development.net/ej9EGdp/2

要将其与将 CSV 数据转换为 XML 的第一步相结合,您可以使用

<?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:map="http://www.w3.org/2005/xpath-functions/map"
    xmlns="http://www.w3.org/2005/xpath-functions"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:param name="csv-string" as="xs:string">january,february,march
1,2,3
1,2,3
1,2,3
</xsl:param>

  <xsl:output method="text"/>

  <xsl:template match="/">
      <xsl:variable name="csv-data-as-xml">
        <Sales xmlns="">
            <xsl:variable name="csv" select="$csv-string"/>
                    <!--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)">
                                <Month>
                                    <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>
                                </Month>
                            </xsl:if>
                        </xsl:non-matching-substring>
                    </xsl:analyze-string>
        </Sales>          
      </xsl:variable>

      <xsl:variable name="xml-rep-of-json">
          <xsl:apply-templates select="$csv-data-as-xml/node()"/>
      </xsl:variable>

      <xsl:value-of select="xml-to-json($xml-rep-of-json, map { 'indent' : true() })"/>

  </xsl:template>

  <xsl:template match="Sales">
      <array>
          <xsl:apply-templates/>
      </array>
  </xsl:template>

  <xsl:template match="Month">
      <map>
          <xsl:apply-templates/>
      </map>
  </xsl:template>

  <xsl:template match="Month/*" expand-text="yes">
      <string key="{local-name()}">{.}</string>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/ej9EGdp/3


推荐阅读