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
CodePudding user response:
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')
}