Home > database >  Remove the root tag of the XML but keep the contents inside it
Remove the root tag of the XML but keep the contents inside it

Time:11-22

I am using the below code to enable the user to select an XML file, and then the code deletes the <metadata> tag from the XML, and replaces it by the modified one;

Sub Button1_Click()
    Dim fso As Object, ts As Object, doc As Object
    Dim data As Object, filename As String
    Dim ws As Worksheet
    Set ws = ActiveSheet
    
    ' select file
    With Application.FileDialog(msoFileDialogFilePicker)
        If .Show <> -1 Then Exit Sub
        filename = .SelectedItems(1)
    End With
    
    ' read file and add top level
    Set doc = CreateObject("MSXML2.DOMDocument.6.0")
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set ts = fso.OpentextFile(filename)
    doc.LoadXML Replace(ts.readall, "<metadata>", "<root><metadata>", 1, 1) & "</root>" '<metadata> removed
    ts.Close
    
    ' import data tag only
    Dim s As String
    Set data = doc.getElementsByTagName("data")(0)
    s = data.XML
    ' MsgBox s
    
    Set ts = fso.CreateTextFile(filename, True)
    ts.Write s
    ts.Close
    
    MsgBox s 'works perfectly
End Sub

The above code worked perfectly for me, when I was assigned to work with an XML like this - enter image description here

But now, I have a different XML to deal with, which is like - (difference : the ajson root tag)

enter image description here

How do I delete the ajson opening and closing tags, so I get my desired result? Kindly guide... Thanks!

CodePudding user response:

Here is how to do it via XSLT transformation.

XSLT in VBA: Excel VBA Coding for xls transformation

Input XML

<?xml version="1.0"?>
<ajson:json xmlns:ajson="http://www.google.com">
    <metadata>
        <sample>Hi</sample>
    </metadata>
    <data>
        <catalog>
            <book id="bk101">
                <author>Gambardella, Matthew</author>
                <title>XML Developer's Guide</title>
            </book>
        </catalog>
    </data>
</ajson:json>

XSLT

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ajson="http://www.google.com">
    <xsl:output method="xml" encoding="utf-8" indent="yes" omit-xml-declaration="yes"/>
    <xsl:strip-space elements="*"/>

    <!-- template to copy without a namespace-->
    <xsl:template match="*">
        <xsl:element name="{local-name()}">
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates/>
        </xsl:element>
    </xsl:template>

    <!-- template to remove document's root element -->
    <xsl:template match="/*">
        <xsl:apply-templates select="node()"/>
    </xsl:template>

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

    <xsl:template match="metadata">
    </xsl:template>
</xsl:stylesheet>

Output XML

<data>
  <catalog>
    <book id="bk101">
      <author>Gambardella, Matthew</author>
      <title>XML Developer's Guide</title>
    </book>
  </catalog>
</data>

CodePudding user response:

Since your XML format seems to be variable maybe a simple text processing script is all you need.

Option Explicit

Sub Button1_Click()
    Dim fso As Object, ts As Object, filename As String
    Dim s As String, sOut As String, bData As Boolean
    
    'select file
    With Application.FileDialog(msoFileDialogFilePicker)
        If .Show <> -1 Then Exit Sub
        filename = .SelectedItems(1)
    End With
    
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set ts = fso.OpentextFile(filename)
   
    ' capture between <data> .... </data>
    Do While ts.AtEndOfStream <> True
        s = ts.readline
        If Trim(s) = "<data>" Then bData = True
        If bData Then sOut = sOut & s & vbCrLf
        If Trim(s) = "</data>" Then bData = False
    Loop
    Set ts = fso.CreateTextFile(filename, True)
    ts.Write sOut
    ts.Close
    MsgBox sOut
    
End Sub
  • Related