使用 XSLT 在文本文件 (CSV) 中解析 XML 文件

Posted

技术标签:

【中文标题】使用 XSLT 在文本文件 (CSV) 中解析 XML 文件【英文标题】:XML file Parsing in text file (CSV) using XSLT 【发布时间】:2020-04-13 14:12:31 【问题描述】:

尝试使用 XSLT 将下面提到的 XML 文件解析为 CSV。下面提到的使用 XSL 解析的 .CSV 文件中的 XML 文件的预期结果

下面提到了示例 XML 文件

<SCHOOLS>
    <SCHOOL_DATA>
        <SCHOOL>
            <SCHOOL_NAME>Convent International</SCHOOL_NAME>
            <SCHOOL_ADDRESS>Near x-Street</SCHOOL_ADDRESS>
        </SCHOOL>
        <STUDENT_DTLS>
            <STUDENT>
                <STUDENT_NAME>Maria</STUDENT_NAME>
                <STUDENT_CLASS>10</STUDENT_CLASS>
            </STUDENT>
            <STUDENT>
                <STUDENT_NAME>John</STUDENT_NAME>
                <STUDENT_CLASS>12</STUDENT_CLASS>
            </STUDENT>
        </STUDENT_DTLS>
        <SCHOOL_AWARDS>
            <AWARDS>
                <AWARD_NAME>A1</AWARD_NAME>
                <AWARD_DATE>D1</AWARD_DATE>
            </AWARDS>
            <AWARDS>
                <AWARD_NAME>A2</AWARD_NAME>
                <AWARD_DATE>D2</AWARD_DATE>
            </AWARDS>
            <AWARDS>
                <AWARD_NAME>A3</AWARD_NAME>
                <AWARD_DATE>D3</AWARD_DATE>
            </AWARDS>
            <AWARDS>
                <AWARD_NAME>A4</AWARD_NAME>
                <AWARD_DATE>D4</AWARD_DATE>
            </AWARDS>
        </SCHOOL_AWARDS>
    </SCHOOL_DATA>
</SCHOOLS>

使用 Xsl 解析和上述示例数据在 .csv 中的预期输出

SCHOOL_NAME,SCHOOL_ADDRESS,STUDENT_NAME,STUDENT_CLASS,AWARD_NAME,AWARD_DATE
Convent International,Near x-Street,Maria,10,A1,D1
,,John,12,A2,D2
,,,,A3,D3
,,,,A4,D4

开始解析xml文件

SCHOOL_NAME,SCHOOL_ADDRESS,STUDENT_NAME,STUDENT_CLASS,AWARD_NAME,AWARD_DATE
Convent International,Near x-Street
,,Maria,10
,,John,12
,,,,A1,D1
,,,,A2,D2
,,,,A3,D3
,,,,A4,D4

Xslt 文件

<xsl:output method="text" omit-xml-declaration="yes" indent="no"/>
<xsl:template match="/">
SCHOOL_NAME,SCHOOL_ADDRESS,STUDENT_NAME,STUDENT_CLASS,AWARD_NAME,AWARD_DATE
<xsl:for-each select="SCHOOLS/SCHOOL_DATA"> 
<xsl:for-each select="SCHOOL"> 
    <xsl:value-of select="concat(SCHOOL_NAME,',',SCHOOL_ADDRESS,'&#xA;')"/>
</xsl:for-each>
<xsl:for-each select="STUDENT_DTLS/STUDENT"> 
    <xsl:value-of select="concat('',',','',',',STUDENT_NAME,',',STUDENT_CLASS,'&#xA;')"/>
</xsl:for-each>

<xsl:for-each select="SCHOOL_AWARDS/AWARDS"> 
    <xsl:value-of 
select="concat('',',','',',','',',','',',',AWARD_NAME,',',AWARD_DATE,'&#xA;')"/>
</xsl:for-each>
    </xsl:for-each>
</xsl:template>

【问题讨论】:

您的预期输出将一等奖与一等学生相关联,二等奖与二等学生相关联。我在源 XML 中没有看到这样的关联。请澄清这里需要应用的逻辑。 【参考方案1】:

如果(看起来)您只想在第 1 列和第 2 列中列出所有学校,在第 3 和第 4 列中列出所有学生,在第 5 和第 6 列中列出所有奖项,但两者之间没有联系三个列表,然后尝试:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>

<xsl:template match="/SCHOOLS">
    <!-- header -->
    <xsl:text>SCHOOL_NAME,SCHOOL_ADDRESS,STUDENT_NAME,STUDENT_CLASS,AWARD_NAME,AWARD_DATE&#10;</xsl:text>
    <!-- generate rows -->
    <xsl:call-template name="write-rows">
        <xsl:with-param name="schools" select="SCHOOL_DATA/SCHOOL"/>
        <xsl:with-param name="students" select="SCHOOL_DATA/STUDENT_DTLS/STUDENT"/>
        <xsl:with-param name="awards" select="SCHOOL_DATA/SCHOOL_AWARDS/AWARDS"/>
    </xsl:call-template>
</xsl:template>

<xsl:template name="write-rows">
    <xsl:param name="schools"/>
    <xsl:param name="students"/>
    <xsl:param name="awards"/>
    <xsl:param name="i" select="1"/>
    <!-- SCHOOL -->
    <xsl:value-of select="$schools[$i]/SCHOOL_NAME"/>
    <xsl:text>,</xsl:text>  
    <xsl:value-of select="$schools[$i]/SCHOOL_ADDRESS"/>
    <xsl:text>,</xsl:text>  
    <!-- STUDENT -->
    <xsl:value-of select="$students[$i]/STUDENT_NAME"/>
    <xsl:text>,</xsl:text>  
    <xsl:value-of select="$students[$i]/STUDENT_CLASS"/>
    <xsl:text>,</xsl:text>  
    <!-- AWARD -->
    <xsl:value-of select="$awards[$i]/AWARD_NAME"/>
    <xsl:text>,</xsl:text>  
    <xsl:value-of select="$awards[$i]/AWARD_DATE"/>
    <xsl:text>&#10;</xsl:text>  
    <!-- recursive call -->
    <xsl:if test="$i &lt; count($students) or $i &lt; count($awards)">
        <xsl:call-template name="write-rows">
            <xsl:with-param name="schools" select="$schools"/>
            <xsl:with-param name="students" select="$students"/>
            <xsl:with-param name="awards" select="$awards"/>
            <xsl:with-param name="i" select="$i + 1"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>

</xsl:stylesheet>

【讨论】:

以上是关于使用 XSLT 在文本文件 (CSV) 中解析 XML 文件的主要内容,如果未能解决你的问题,请参考以下文章

使用 XSLT 2.0/3.0 使用多个步骤将 CDATA 中的纯文本解析为 html。那里的一部分

使用 XSLT 将 CSV 文件转换为 XML

在xslt中的单个标签下解析多个标签的文本

XSLT 创建 CSV 但维护来自 XML 节点的逗号

将嵌套的 JSON 解析为 CSV

使用 Node/Express 解析 CSV 文件会吐出奇怪的 \x001 代码