使用XSLT帮助将XML转换为CSV

使用XSLT帮助将XML转换为CSV,xslt,csv,Xslt,Csv,我想使用XSLT将XML转换为CSV,但在根据我的输入应用来自SO线程的XSL时: <WhoisRecord> <DomainName>127.0.0.1</DomainName> <RegistryData> <AbuseContact> <Email>abuse@iana.org</Email> <Name>Internet Corporation for

我想使用XSLT将XML转换为CSV,但在根据我的输入应用来自SO线程的XSL时:

<WhoisRecord> <DomainName>127.0.0.1</DomainName> <RegistryData> <AbuseContact> <Email>abuse@iana.org</Email> <Name>Internet Corporation for Assigned Names and Number</Name> <Phone>+1-310-301-5820</Phone> </AbuseContact> <AdministrativeContact i:nil="true"/> <BillingContact i:nil="true"/> <CreatedDate/> <RawText>...</RawText> <Registrant> <Address>4676 Admiralty Way, Suite 330</Address> <City>Marina del Rey</City> <Country>US</Country> <Name>Internet Assigned Numbers Authority</Name> <PostalCode>90292-6695</PostalCode> <StateProv>CA</StateProv> </Registrant> <TechnicalContact> <Email>abuse@iana.org</Email> <Name>Internet Corporation for Assigned Names and Number</Name> <Phone>+1-310-301-5820</Phone> </TechnicalContact> <UpdatedDate>2010-04-14</UpdatedDate> <ZoneContact i:nil="true"/> </RegistryData> </WhoisRecord> 我的问题是,生成的转换缺少节点(如包含IP地址的DomainName元素),并且一些子节点连接起来没有逗号(如AbuseContact的子节点)

我希望看到CSV格式的所有XML输出,以及如下字符串:abuse@iana.orgInternet指定名称和编号公司+1-310-301-5820,“以逗号分隔

我的XSL已经很生锈了。感谢您的帮助。:)

下面是我正在使用的XSL:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text" encoding="iso-8859-1"/> <xsl:strip-space elements="*" /> <xsl:template match="/*/child::*"> <xsl:for-each select="child::*"> <xsl:if test="position() != last()"><xsl:value-of select="normalize-space(.)"/>, </xsl:if> <xsl:if test="position() = last()"><xsl:value-of select="normalize-space(.)"/><xsl:text> </xsl:text> </xsl:if> </xsl:for-each> </xsl:template> </xsl:stylesheet> ,
我相信你需要递归的解决方案来解决这个问题。因此,您需要一些不断深入到树中直到到达text()节点的内容。如果该text()节点实际上是最后一个节点的子节点,则它会放置一个新行。否则,它只是将值加上逗号

如果节点没有text()节点作为其子节点,则递归地开始挖掘该树


希望这能有所帮助。

这个简单的转换产生了想要的结果:

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

    <xsl:template match="/">
    <xsl:apply-templates select="//text()"/>
    </xsl:template>

    <xsl:template match="text()">
      <xsl:copy-of select="."/>
      <xsl:if test="not(position()=last())">,</xsl:if>
    </xsl:template>
</xsl:stylesheet>

,
注意以下事项的使用:

 <xsl:strip-space elements="*"/>

放弃任何仅限空白的文本节点


更新:AJ提出了一个问题,即结果应该按每行的recirds/元组进行分组。问题中没有定义记录/元组到底应该是什么。因此,当前的解决方案解决了仅空白文本节点和缺少逗号这两个问题,但其目的不是将输出转换为记录/元组。

好问题(+1)。有关简单的解决方案,请参见我的答案。:)为什么我的答案被否决了?对此发表评论可能会有所帮助。我自己是XSLT新手。可能是因为不需要显式递归或循环来沿子轴移动。CSV不需要新行来分隔记录集/记录元组吗?从这个问题上看,什么构成记录元组并不清楚——这在关系数据库世界中有意义,但是对于树,需要显式定义。我还编辑了我的答案以反映你们的评论。谢谢大家!我想要一组唱片。那有多难?我还希望能够将XSL应用于结构类似的XML文档——首选不按名称引用元素的解决方案。再次感谢。:)@Adam Kahtava:一旦定义了元组应该由什么组成,实现元组/集合就不难了。有些字段(嗯,address元素)中有逗号,所以您可能需要对此进行检查,并用引号将字段括起来。如果这个字段包含引号,我相信它必须变成双引号。
"127.0.0.1", "abuse@iana.org", "Internet Corporation for Assigned Names and Number", "+1-310-301-5820", "...", "4676 Admiralty Way, Suite 330", "Marina del Rey", "US", "Internet Assigned Numbers Authority", "90292-6695", "CA", "abuse@iana.org", "Internet Corporation for Assigned Names and Number", "+1-310-301-5820", "2010-04-14"
<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>
 <xsl:strip-space elements="*"/>

    <xsl:template match="/">
    <xsl:apply-templates select="//text()"/>
    </xsl:template>

    <xsl:template match="text()">
      <xsl:copy-of select="."/>
      <xsl:if test="not(position()=last())">,</xsl:if>
    </xsl:template>
</xsl:stylesheet>
 <xsl:strip-space elements="*"/>