在Powershell中添加回车以手动漂亮打印大型XML文件

问题描述 投票:1回答:1

我有一个非常大的(280 Meg)xml文件,它都在一行上。我有几个编辑器几乎无法打开它,但没有什么能让我打印它。

我试图在Powershell中对其进行格式化,但还是无法弄清楚语法。我想要使​​文件更具可读性的方法是用回车符+换行符和结束标记替换所有结束标记,但我无法让它工作。

这是我到目前为止所尝试的:

(get-content .\ReallyHugeXMLFile2.xml) -replace ('</','`n</') | out-file .\ReallyHugeXMLFile2Formatted.xml
(get-content .\ReallyHugeXMLFile2.xml) -replace ('</','\r\n</') | out-file .\ReallyHugeXMLFile2Formatted2.xml
(get-content .\ReallyHugeXMLFile2.xml) -replace ('</','\\r\\n</') | out-file .\ReallyHugeXMLFile2Formatted3.xml

谢谢

xml powershell pretty-print
1个回答
2
投票

TheIncorrigible1在评论中提供了关键指针:

假设你的大型XML文件仍然可以作为一个整体加载到System.Xml.XmlDocument实例中,你可以简单地调用它的.Save()方法来创建一个漂亮的打印输出文件(这样就不需要手动换行了;另外,使用一个XML解析器总是优于文本操作)。

# Load the file into a [xml] (System.Xml.XmlDocument) instance...
($xmlDoc = New-Object xml).Load($PWD.ProviderPath + '/HugeFile.xml')
# ... and save it, which automatically pretty-prints it.
$xmlDoc.Save($PWD.ProviderPath + '/HugeFilePrettyPrinted.xml')

请注意需要在文件名前加上$PWD.ProviderPath,以确保.NET使用PowerShell的当前目录(.NET通常不同,.NET不知道使用New-PSDrive创建的PowerShell驱动器)。[1]

注意:生成的文件将只有LF换行符,而不是CRLF换行符。


可行性论证:

首先,运行以下代码(PSv5 +)以创建大小约为280 MB的示例XML文件。请注意,您可以轻松调整代码以指定不同的目标大小。

注意:

  • 文件HugeFile.xml将在当前目录中创建,并且稍后运行pretty-printing命令会在同一位置创建(甚至更大)HugeFilePrettyPrinted.xml
  • 创建此文件可能需要几分钟。
# Create a sample single-line XML file of a given size (approximately).
# Note: Depending on the target size, this can take a long time to complete.
#       Additionally, for performance reasons the code is written so that
#       the file content must fit into memory as a whole.

# The desired size of the resulting file.
$targetFileSize = 280mb
$targetFile = './HugeFile.xml'

# The XML element to repeat.
$repeatingElementTemplate = '<book><title>De Profundis {0:000000000000}</title></book>'
# Determine how often it must be repeated to reach the target size (approximately)
$repeatCount = $targetFileSize / ($repeatingElementTemplate.Length - 4)

Write-Verbose -vb "Creating XML file '$targetFile' of approximate size $('{0:N2}' -f ($targetFileSize / 1mb)) MB..."
# Create the file.
'<?xml version="1.0"?><catalog>' | Set-Content -NoNewline -Encoding Utf8 $targetFile
-join (1..$repeatCount).ForEach({ $repeatingElementTemplate -f $_ }) |
  Add-Content -NoNewline -Encoding Utf8 $targetFile
'</catalog>' | Add-Content -NoNewline -Encoding Utf8 $targetFile

然后,运行上面的漂亮打印命令。

在具有3GB RAM(在旧硬件上)的单核Windows 10 VM上,这需要大约40秒。埃里克本人在他的机器上报告不到5秒钟。


[1]确保将相对PowerShell文件系统路径正确传递给.NET方法:

  • 如上所述,.NET的当前目录的概念通常与PowerShell的概念不同,因此相对的PowerShell路径不能按原样使用。
  • 使用$PWD.ProviderPath$PWD.ProviderPath + '<fileInCurrentDir>)形成完整路径可确保PowerShell的当前文件系统位置表示为本机文件系统路径(谢谢,TheIncorrigible1)。 .NET方法只能理解后者;他们不知道使用New-PSDrive创建的自定义PowerShell驱动器,并且他们不知道PowerShell的提供者前缀表示法,当当前位置是UNC路径时$PWD字符串化(例如, Microsoft.PowerShell.Core\FileSystem::\\some-server\some-share\some-folder)。
  • 如果您不使用自定义PowerShell驱动器,并且您没有直接从UNC位置运行代码,则可以更简单地根据当前位置构建完整路径 "$PWD/<fileInCurrentDir>"
  • 相反,为了获得完全的稳健性,您必须使用 (Get-Location -PSProvider FileSystem).ProviderPath + '/<fileInCurrentDir>',因为PowerShell的当前位置可能来自文件系统提供者以外的提供者;例如,HKCU:\Console(注册管理机构提供商)。
© www.soinside.com 2019 - 2024. All rights reserved.