2

I'm facing a problem related to nested zip files in powershell. Currently I have a zip file that contains a second zip file. Inside this second zip file I have a XML file that contains some business data that I need to read and access without extracting any of previous zip files. I'm able to access to the second zip but for now I can't read the XML file located in the second zip, as I'm getting it as a zipentryfile which does not offer any method to read the XML content in stream mode... Could you please provide some hint that helps me getting the required information from the XML file?

This is the hierarchy of my zip files:

OuterZip.zip--|
              |--Folder1---InnerZip.zip--|
                                         |--XMLFile.xml    // Requirement is to read content of XML file

Currently I'm able to retrieve the InnerZip.zip, but I can't read the data inside XMLFile.xml:

[Reflection.Assembly]::LoadWithPartialName('System.IO.Compression.FileSystem')
    $zipFileContent = [IO.Compression.ZipFile]::OpenRead($file.FullName)
    $entries = $zipFileContent.Entries
    $entries | ForEach-Object {
            LogMessage -message "'$($_)'"
            LogMessage -message "'$($_.GetType())'"
            $subEntries = $_.Entries
            $subEntries | ForEach-Object {
                        LogMessage -message "'$($_)'"
                        LogMessage -message "'$($_.GetType())'"
                    }
            }

Thank you in advance

Samou Mc
  • 43
  • 1
  • 5
  • 1
    option 3 or 4 from this answer? (https://stackoverflow.com/a/37561878/724039) – Luuk Jul 10 '22 at 09:16
  • @Luuk the post that you mentioned is referring to 1 zip file containing directly an XML file (1 level depth) but in my case my XML file is inside a second zip file (2 levels). – Samou Mc Jul 10 '22 at 13:32
  • 1
    @zett42 thank you for your reply I will do it ASAP – Samou Mc Jul 10 '22 at 13:33

1 Answers1

3

You basically need to create a ZipArchive from the stream of the entry that is the inner ZIP.

# prefered over LoadWithPartialName
Add-Type -Assembly System.IO.Compression.Filesystem

$xmlStream = $innerArchiveStream = $innerArchive = $outerArchive = $null

try {
    # Open outer ZIP as an archive
    $outerArchive = [IO.Compression.ZipFile]::OpenRead("$PWD\OuterZip.zip")

    # Find the entry that is the inner ZIP
    $innerArchiveEntry = $outerArchive.Entries | Where-Object FullName -eq 'folder1/innerzip.zip'
    if( -not $innerArchiveEntry ) {
        throw 'Could not find innerzip.zip'
    }

    # Open inner ZIP as a stream
    $innerArchiveStream = $innerArchiveEntry.Open()
    # Create archive from the stream
    $innerArchive = [IO.Compression.ZipArchive]::new( $innerArchiveStream )

    # Find the XML file in the inner ZIP
    $xmlEntry = $innerArchive.Entries | Where-Object FullName -eq 'xmlfile.xml'
    if( -not $xmlEntry ) {
        throw 'Could not find xmlfile.xml'
    }

    # Open XML file as stream
    $xmlStream = $xmlEntry.Open()

    # Load XML document from the stream
    $xml = [xml]::new(); $xml.Load( $xmlStream )
    $xml.InnerXml   # output the XML
}
finally {
    # Cleanup
    ($xmlStream, $innerArchiveStream, $innerArchive, $outerArchive).ForEach('Dispose')
}
zett42
  • 25,437
  • 3
  • 35
  • 72