简体   繁体   中英

Convert XML to CSV using vba

I have a 20 files with XML and it contain data like this:

<?xml version="1.0" encoding="UTF-8"?>
<measCollecFile xmlns="http://www.3gpp.org/ftp/specs/archive/32_series/32.435#measCollec">
<fileHeader fileFormatVersion="32.435 V10.0" vendorName="Nokia Networks">
<fileSender elementType="LNBTS"/>
<measCollec beginTime="2018-01-17T00:00:00+00:00"/>
</fileHeader>
<measData>
<managedElement/>
<measInfo measInfoId="LTE_Cell_Load">
<granPeriod endTime="2018-01-17T00:15:00+00:00" duration="PT900S"/>
<measTypes>M8001C0 M8001C1 M8001C10 M8001C100 M8001C101 M8001C102 M8001C103 M8001C104 M8001C105 M8001C106 M8001C107 M8001C108 M8001C109 M8001C11 M8001C110 M8001C111 M8001C112 M8001C113 M8001C114 M8001C115 M8001C116 M8001C117 M8001C118 M8001C119 M8001C12 M8001C120 M8001C121 M8001C122 M8001C123 M8001C124 M8001C125 M8001C126 M8001C127 M8001C128 M8001C129 M8001C13 M8001C130 M8001C131 M8001C132 M8001C133 M8001C135 M8001C136 M8001C137 M8001C138 M8001C139 M8001C14 M8001C140 M8001C141 M8001C142 M8001C143 M8001C144 M8001C145 M8001C146 M8001C149 M8001C15 M8001C152 M8001C153 M8001C154 M8001C155 M8001C156 M8001C157 M8001C158 M8001C159 M8001C16 M8001C160 M8001C161 M8001C162 M8001C163 M8001C164 M8001C165 M8001C166 M8001C167 M8001C168 M8001C169 M8001C17 M8001C170 M8001C171 M8001C172 M8001C173 M8001C174 M8001C175 M8001C176 M8001C177 M8001C178 M8001C179 M8001C18 M8001C180 M8001C181 M8001C182 M8001C183 M8001C184 M8001C185 M8001C186 M8001C187 M8001C188 M8001C189 M8001C19 M8001C190 M8001C191 M8001C192 M8001C193 M8001C194 M8001C195 M8001C196 M8001C197 M8001C2 M8001C20 M8001C202 M8001C203 M8001C204 M8001C205 M8001C206 M8001C207 M8001C208 M8001C209 M8001C21 M8001C210 M8001C211 M8001C212 M8001C213 M8001C214 M8001C215 M8001C216 M8001C217 M8001C218 M8001C219 M8001C22 M8001C220 M8001C222 M8001C23 M8001C231 M8001C232 M8001C233 M8001C24 M8001C25 M8001C26 M8001C269 M8001C27 M8001C270 M8001C271 M8001C272 M8001C273 M8001C274 M8001C275 M8001C276 M8001C277 M8001C278 M8001C279 M8001C28 M8001C280 M8001C281 M8001C286 M8001C29 M8001C291 M8001C292 M8001C293 M8001C294 M8001C299 M8001C3 M8001C30 M8001C300 M8001C305 M8001C306 M8001C307 M8001C308 M8001C309 M8001C31 M8001C310 M8001C311 M8001C312 M8001C313 M8001C314 M8001C315 M8001C316 M8001C317 M8001C32 M8001C323 M8001C324 M8001C325 M8001C326 M8001C33 M8001C34 M8001C35 M8001C36 M8001C37 M8001C38 M8001C39 M8001C4 M8001C40 M8001C41 M8001C42 M8001C421 M8001C422 M8001C423 M8001C424 M8001C425 M8001C426 M8001C427 M8001C428 M8001C429 M8001C43 M8001C430 M8001C431 M8001C432 M8001C433 M8001C434 M8001C435 M8001C436 M8001C437 M8001C438 M8001C439 M8001C44 M8001C440 M8001C441 M8001C442 M8001C443 M8001C444 M8001C445 M8001C446 M8001C447 M8001C448 M8001C449 M8001C45 M8001C450 M8001C451 M8001C452 M8001C453 M8001C454 M8001C455 M8001C456 M8001C457 M8001C458 M8001C459 M8001C46 M8001C460 M8001C461 M8001C462 M8001C463 M8001C464 M8001C465 M8001C466 M8001C467 M8001C468 M8001C469 M8001C47 M8001C470 M8001C471 M8001C472 M8001C473 M8001C474 M8001C475 M8001C476 M8001C477 M8001C478 M8001C479 M8001C48 M8001C480 M8001C481 M8001C482 M8001C483 M8001C484 M8001C485 M8001C486 M8001C487 M8001C488 M8001C49 M8001C5 M8001C50 M8001C51 M8001C52 M8001C53 M8001C54 M8001C55 M8001C56 M8001C57 M8001C58 M8001C59 M8001C6 M8001C60 M8001C61 M8001C62 M8001C63 M8001C64 M8001C65 M8001C66 M8001C67 M8001C68 M8001C69 M8001C7 M8001C70 M8001C71 M8001C72 M8001C73 M8001C74 M8001C75 M8001C76 M8001C77 M8001C78 M8001C79 M8001C8 M8001C80 M8001C81 M8001C82 M8001C83 M8001C84 M8001C85 M8001C86 M8001C87 M8001C88 M8001C89 M8001C9 M8001C90 M8001C91 M8001C92 M8001C93 M8001C94 M8001C95 M8001C96 M8001C97 M8001C98 M8001C99</measTypes>
<measValue measObjLdn="PLMN-PLMN/MRBTS-101/LNBTS-101/LNCEL-4,PLMN-PLMN/MCC-310/MNC-090">
<measResults>0 0 90000 0 0 0 0 0 0 0 0 0 0 56250 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 15 12 146250 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0</measResults>
</measValue>
</measInfo>
<fileFooter>
<measCollec endTime="2018-01-17T00:15:00+00:00"/>
</fileFooter>
</measCollecFile>

I am looking for output in Excel as under:

| Day        | Time  | DN                                    | Measure Info  | Counter   | Value |    
|------------|-------|---------------------------------------|---------------|-----------|-------|
| 1/17/2018  | 15:00 | PLMN-PLMN/MRBTS-101/LNBTS-101/LNCEL-4 | LTE_Cell_Load | M8001C0   | 0     |
| 1/17/2018  | 15:00 | PLMN-PLMN/MRBTS-101/LNBTS-101/LNCEL-4 | LTE_Cell_Load | M8001C1   | 0     |
| 1/17/2018  | 15:00 | PLMN-PLMN/MRBTS-101/LNBTS-101/LNCEL-4 | LTE_Cell_Load | M8001C10  | 9000  |
| 1/17/2018  | 15:00 | PLMN-PLMN/MRBTS-101/LNBTS-101/LNCEL-4 | LTE_Cell_Load | M8001C100 | 0     |

There will be 6 columns Day: coming from Grant Period Time: coming from Grant Period DN: coming from measValue measObjLdn Measure Info:

Each counter has corresponding value in the measResult table. There is 0 if the value was not there. Obviously there will more items in measTypes and corresponding measValues

Each XML contain 1 to 20 sets of measInfo measInfoId and there are 20+ sheets for me to convert.

Looking for a single csv based on multiple selected XML files. All XML have same structure.

Looking forward for your support.

Consider XSLT (sibling to XPath) which is the special-purpose language designed to transform XML files including conversion to text files like CSV. With VBA's MSXML , you can run XSLT 1.0 scripts without any For looping or If logic.

First, you need to append all 20 XML files into one master XML file which requires using XSLT's document() function in order to output a singular master CSV. Then, you need to split measType and measResults texts by space delimiter, which requires a recursive template call such as @DimitreNovatchev's answer . Then bind the indicator values, date , time , etc. at different locations with XPath's ancestor::* or following-sibling::* .

XSLT - XML Append (save as .xsl file -a special .xml file)

Save all XMLs in same directory. Change document names in document() to actuals and be sure to leave out first XML. It is assumed all XMLs have same default namespace: http://www.3gpp.org/ftp/specs/archive/32_series/32.435#measCollec .

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                              xmlns:doc="http://www.3gpp.org/ftp/specs/archive/32_series/32.435#measCollec">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="doc:measData">
    <xsl:copy><xsl:apply-templates select="*"/></xsl:copy>
    <xsl:copy-of select="document('XML_2.xml')/doc:measCollecFile/doc:measData"/>
    <xsl:copy-of select="document('XML_3.xml')/doc:measCollecFile/doc:measData"/>
    <xsl:copy-of select="document('XML_4.xml')/doc:measCollecFile/doc:measData"/>
    <xsl:copy-of select="document('XML_5.xml')/doc:measCollecFile/doc:measData"/>
    ...
  </xsl:template>

</xsl:stylesheet>

XSLT - CSV Conversion (save as .xsl file)

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                              xmlns:doc="http://www.3gpp.org/ftp/specs/archive/32_series/32.435#measCollec">
  <xsl:output indent="yes" method="text"/>
  <xsl:strip-space elements="*"/>

  <xsl:param name="delimiter">,</xsl:param>

  <xsl:template match="/doc:measCollecFile">
      <xsl:text>date,time,DN,Measure Info,Counter,Value&#xa;</xsl:text>
      <xsl:apply-templates select="doc:measData"/>
  </xsl:template>

  <xsl:template match="doc:measData">
    <xsl:apply-templates select="doc:measInfo"/>
  </xsl:template>

  <xsl:template match="doc:measInfo">
    <xsl:apply-templates select="doc:measTypes"/>
  </xsl:template>

 <xsl:template match="doc:measTypes" name="split">
    <xsl:param name="dateTime" select="ancestor::doc:measInfo/doc:granPeriod/@endTime"/>
    <xsl:param name="date" select="substring($dateTime,1,10)"/>
    <xsl:param name="time" select="substring($dateTime,16,20)"/>
    <xsl:param name="dn" select="substring-before(following-sibling::doc:measValue/@measObjLdn, ',')"/>
    <xsl:param name="info" select="ancestor::doc:measInfo/@measInfoId"/>

    <xsl:param name="pText" select="."/>
    <xsl:param name="vText" select="following-sibling::doc:measValue/doc:measResults"/>
    <xsl:if test="string-length($pText)">
         <xsl:value-of select="concat($date, $delimiter, $time, $delimiter, $dn,  $delimiter, $info, $delimiter, 
                                      substring-before(concat($pText,' '),' '), $delimiter, substring-before(concat($vText,' '),' '))"/>
         <xsl:text>&#xa;</xsl:text>                                   
         <xsl:call-template name="split">
            <xsl:with-param name="pText" select="substring-after($pText, ' ')"/>
            <xsl:with-param name="vText" select="substring-after($vText, ' ')"/>
         </xsl:call-template>
    </xsl:if>
 </xsl:template>

</xsl:stylesheet>

VBA

Consists of two macros: load very first XML in Append_XML(), use generated Master.xml in CSV_Convert() .

Sub Append_XML()
   ' REFERENCE Microsoft XML, v##
    Dim xmlDoc As New MSXML2.DOMDocument, xslDoc As New MSXML2.DOMDocument, newDoc As New MSXML2.DOMDocument

    ' LOAD XML AND XSL FILES
    xslDoc.async = False
    xmlDoc.Load "C:\Path\To\XML_1.xml"

    xslDoc.async = False
    xslDoc.Load "C:\Path\To\Append_XSLT_Script.xsl"

    ' TRANSFORM XML
    xmlDoc.transformNodeToObject xslDoc, newDoc

    ' SAVE XML
    newDoc.Save "C:\Path\To\Master.xml"

    MsgBox "Successfully appended XMLs together!", vbInformation

    Set xmlDoc = Nothing: Set xslDoc = Nothing: Set newDoc = Nothing

End Sub


Sub CSV_Convert()
    Dim xmlDoc As New MSXML2.DOMDocument, xslDoc As New MSXML2.DOMDocument
    Dim xmlstr As String, lastRow As Long
    Dim fso As Object, oFile As Object

    ' LOAD XML AND XSL FILES
    xslDoc.async = False
    xmlDoc.Load "C:\Path\To\Master.xml"

    xslDoc.async = False
    xslDoc.Load "C:\Path\To\CSV_Conversion_XSLT_Script.xsl"

    ' TRANSFORM XML
    xmlstr = xmlDoc.transformNode(xslDoc)

    ' SAVE CSV
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set oFile = fso.CreateTextFile("C:\Path\To\Final_Output.csv")

    oFile.WriteLine xmlstr
    oFile.Close

    MsgBox "Successfully converted XML to CSV!", vbInformation

    Set xmlDoc = Nothing: Set xslDoc = Nothing
    Set oFile = Nothing: Set fso = Nothing

End Sub

Output (321 records with above post but more with Master.xml)

' date,time,DN,Measure Info,Counter,Value
' 2018-01-17,5:00+00:00,PLMN-PLMN/MRBTS-101/LNBTS-101/LNCEL-4,LTE_Cell_Load,M8001C0,0
' 2018-01-17,5:00+00:00,PLMN-PLMN/MRBTS-101/LNBTS-101/LNCEL-4,LTE_Cell_Load,M8001C1,0
' 2018-01-17,5:00+00:00,PLMN-PLMN/MRBTS-101/LNBTS-101/LNCEL-4,LTE_Cell_Load,M8001C10,90000
' 2018-01-17,5:00+00:00,PLMN-PLMN/MRBTS-101/LNBTS-101/LNCEL-4,LTE_Cell_Load,M8001C100,0
' 2018-01-17,5:00+00:00,PLMN-PLMN/MRBTS-101/LNBTS-101/LNCEL-4,LTE_Cell_Load,M8001C101,0
' 2018-01-17,5:00+00:00,PLMN-PLMN/MRBTS-101/LNBTS-101/LNCEL-4,LTE_Cell_Load,M8001C102,0
' 2018-01-17,5:00+00:00,PLMN-PLMN/MRBTS-101/LNBTS-101/LNCEL-4,LTE_Cell_Load,M8001C103,0
' 2018-01-17,5:00+00:00,PLMN-PLMN/MRBTS-101/LNBTS-101/LNCEL-4,LTE_Cell_Load,M8001C104,0
' 2018-01-17,5:00+00:00,PLMN-PLMN/MRBTS-101/LNBTS-101/LNCEL-4,LTE_Cell_Load,M8001C105,0
' 2018-01-17,5:00+00:00,PLMN-PLMN/MRBTS-101/LNBTS-101/LNCEL-4,LTE_Cell_Load,M8001C106,0
' 2018-01-17,5:00+00:00,PLMN-PLMN/MRBTS-101/LNBTS-101/LNCEL-4,LTE_Cell_Load,M8001C107,0
' ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM