У меня есть около ста файлов XML (с той же структурой), и я хочу импортировать их в SAS. К сожалению, при этом у меня есть некоторые проблемы, связанные с файлом MAP файлов XML (у меня нет файла MAP для этих файлов). Так что я хоть конвертировал эти файлы в CSV через Excel. Но если я использую этот путь, мне нужно что-то, что способно массово конвертировать все мои XML-файлы в CSV, потому что, очевидно, я не могу вручную конвертировать каждый файл в отдельности.

Кто-нибудь знает, как я могу решить?

Благодарю.

3 ответа3

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
0

Поскольку вы, кажется, знакомы с 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"))
}
0

Для следующего кода вы можете использовать любой процессор 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. Насколько я его протестировал, он работает для всех случаев, описанных в спецификации. Но, честно говоря, я не могу этого гарантировать. Вы должны проверить это и дать некоторую обратную связь здесь.

Однако вот код XSLT-2.0, который преобразует XML в CSV:

<?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>&#xa;</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>&#xa;</xsl:text>
    </xsl:template>

    <xsl:template match="text()">
      <xsl:choose>
        <xsl:when test=".='&quot;&quot;'">
          <xsl:value-of select="'&quot;&quot;'" />
        </xsl:when>
        <xsl:when test="contains(.,',') or contains(.,'&#xa;')">
          <xsl:value-of select="concat('&quot;',.,'&quot;')" />
        </xsl:when>
        <xsl:when test="contains(.,'&quot;')">
          <xsl:value-of select="replace(.,'&quot;','&quot;&quot;')" />
        </xsl:when>
        <xsl:when test="contains(.,',') and contains(.,'&quot;')">
          <xsl:value-of select="concat('&quot;',replace(.,'&quot;','&quot;&quot;'),'&quot;')" />
        </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 одновременно.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .