我有大约一百个 XML 文件(具有相同的结构),我想将它们导入 SAS。不幸的是,在这样做时,我遇到了一些与 XML 文件的 MAP 文件相关的问题(我没有这些文件的 MAP 文件)。所以我想通过 Excel 将这些文件转换为 CSV。但如果我使用这种方法,我需要能够将所有 XML 文件大规模转换为 CSV 的东西,因为显然我无法手动逐个转换每个文件。
有谁知道我该如何解决?
谢谢。
答案1
我已经用这个 VBA 脚本解决了我的问题:
Public Sub ConvertXmlToXlsx()
Application.DisplayAlerts = False
Dim objFSO As Object
Dim objFolder As Object
Dim objFile As Object
xmlFolder = "C:\Users\xxx\xxx\xxx\xxx\"
convFolder = "C:\Users\xxx\xxx\xxx\xxx\"
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFolder = objFSO.GetFolder(xmlFolder)
For Each objFile In objFolder.Files
If UCase(Right(objFile.Name, Len(XML))) = UCase(XML) Then
NewFileName = convFolder & objFile.Name & ".xlsx"
Workbooks.OpenXML (objFolder & "\" & objFile.Name), LoadOption:=xlXmlLoadImportToList
ActiveWorkbook.SaveAs Filename:=NewFileName
ActiveWorkbook.Close
End If
Next objFile
End Sub
答案2
由于您似乎熟悉 SAS,或者您很快就会熟悉,我会使用 R 读出 Excel 文件,然后将它们再次写入 CSV。
下面的代码允许您设置工作目录,将内容读入列表并遍历列表以在几行中转换文件。
library(readxl)
setwd("The directory containing your files")
list <- list.files()
for(i in 1:length(list)) {
Intermediate <- read_excel(list[i])
write.csv(Intermediate, paste0(list[i],".csv"))
}
答案3
对于以下代码,您可以使用任何 XSLT-2.0 处理器将 XML 转换为 CSV 文件。
XML 文件应具有如下结构:
<AnyRoot>
<AnyEntry>
<Value1></Value1>
<Value2></Value2>
<Value3></Value3>
...
</AnyEntry>
<AnyEntry>
<Value1></Value1>
...
</AnyEntry>
...
</AnyRoot>
对于此示例,我使用以下 XML 文件:
<root>
<Entry>
<CSVValue1>A</CSVValue1>
<CSVValue2>"B"</CSVValue2>
<CSVValue3>C,D</CSVValue3>
<CSVValue4>"E","F"</CSVValue4>
</Entry>
<Entry>
<CSVValue1>G H</CSVValue1>
<CSVValue2>""</CSVValue2>
<CSVValue3></CSVValue3>
<CSVValue4 />
</Entry>
<Entry>
<CSVValue1>1996</CSVValue1>
<CSVValue2>Jeep</CSVValue2>
<CSVValue3>Grand Cherokee</CSVValue3>
<CSVValue4>MUST SELL!
air, moon roof, loaded</CSVValue4>
<CSVValue5>4999.00</CSVValue5>
</Entry>
</root>
这是 XSLT-2.0 样式表,可用于将所有 XML 文件转换为 CSV 文件。据我测试,它适用于规范中描述的所有情况。但说实话,我不能保证。你必须测试一下并在这里给出一些反馈。
但是,这里是将 XML 转换为 CSV 的 XSLT-2.0 代码:
<?xml version='1.0' encoding='utf-8'?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" omit-xml-declaration="yes" indent="yes"/>
<!-- ================================================================= -->
<!-- XML to CSV Version 1.0 by zx485 on 30-01-2019@01:58 -->
<!-- Run it with java -jar saxon9he.jar -xsl:XML2CSV.xslt input.xml -->
<!-- ================================================================= -->
<xsl:variable name="csvItems">
<xsl:for-each select="/*/*[1]/*">
<Item name="{local-name()}" />
</xsl:for-each>
</xsl:variable>
<xsl:template match="/*">
<xsl:value-of select="$csvItems/Item/@name" separator="," />
<xsl:text>
</xsl:text>
<xsl:apply-templates select="*" />
</xsl:template>
<xsl:template match="/*/*">
<xsl:for-each select="*">
<xsl:apply-templates select="." />
<xsl:if test="position() != last()">
<xsl:text>,</xsl:text>
</xsl:if>
</xsl:for-each>
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template match="text()">
<xsl:choose>
<xsl:when test=".='""'">
<xsl:value-of select="'""'" />
</xsl:when>
<xsl:when test="contains(.,',') or contains(.,'
')">
<xsl:value-of select="concat('"',.,'"')" />
</xsl:when>
<xsl:when test="contains(.,'"')">
<xsl:value-of select="replace(.,'"','""')" />
</xsl:when>
<xsl:when test="contains(.,',') and contains(.,'"')">
<xsl:value-of select="concat('"',replace(.,'"','""'),'"')" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="." />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
输出结果为:
CSVValue1,CSVValue2,CSVValue3,CSVValue4
A,""B"","C,D",""E","F""
G H,"",,
1996,Jeep,Grand Cherokee,"MUST SELL!
air, moon roof, loaded",4999.00
如果将此转换放入脚本循环中,则可以一次转换多个 XML 文件。