【问题标题】:Reading large XML document to generate array of XML nodes in Powershell?读取大型 XML 文档以在 Powershell 中生成 XML 节点数组?
【发布时间】:2013-03-08 10:09:46
【问题描述】:

我有加载 XML 文档的代码,执行 $xmlDoc.SelectNodes($XPath),然后 foreach($node in $nodes) 将 XML 作为字符串插入表中。

此代码适用于 ca. 100KB,包含 10 条记录。

但是,我有一个大约是 ca 的文件。 100MB 和 ca。 50k 条记录和代码只是挂在$xmlDoc =[xml](gc $xmlpath) (并使用所有可用的系统内存)。有没有更好的方法来生成我的数组 $nodes 而无需先解析整个 XML 文档?

# Loads xml document
$xmlpath = $filepath
$xmlDoc =[xml](gc $xmlpath)
$nodes = $xmlDoc.SelectNodes('//root') #One element per record in SQL

...

$SqlQuery = @"
INSERT INTO {0} VALUES ({1})
"@

....

foreach($node in $nodes) 
{ 
$StringWriter = New-Object System.IO.StringWriter 
$XmlWriter = New-Object System.XMl.XmlTextWriter $StringWriter 
$XmlWriter.Formatting = "None" 
$XmlWriter.Flush() 
$StringWriter.Flush() 
$node.WriteTo($XmlWriter) 
#data content (for this quote)
$Pxml = "`'"+$StringWriter.ToString()+"`'"

#Write to database
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = [string]::Format($sqlquery, $tableName, $Pxml)
$SqlCmd.Connection = $SqlConnection
$SqlCmd.ExecuteScalar()
} 

XML 文档具有以下结构:

<xml>
  <root>
   ...
  </root>
  <root>
   ...
  </root>
</xml>

结果字符串的格式为:

<root>
 ...
</root>

【问题讨论】:

    标签: xml sql-server-2008 powershell


    【解决方案1】:

    this link 为基础,试试下面的代码。 $object 应该包含你的根对象

    $object= @()
    type "$filepath" | %{
      if($_.trim() -eq "<root>") {
        $object= @()
        $object+= $_
      }
      elseif($_.trim() -eq "</root>"){
        $object+= $_
        #call the code within your foreach($node in $nodes) {} section here
      } else {
        $object+= $_
      }
     }
    

    【讨论】:

    • 这几乎直接产生了所需的结果。
    【解决方案2】:

    据我所知,XML 解析需要完整的文件在内存中。尝试使用更有效的 .Net 方法来阅读内容。以下应该运行得更快并且可能使用更少的内存,因为它将内容保存为字符串数组,而不是像Get-Content那样的字符串对象数组。

    # Loads xml document
    
    # Get aboslute path
    $xmlpath = (Resolve-Path $filepath).Path
    # Get xml
    $xmlDoc = [xml]([IO.File]::ReadAllLines($xmlpath))
    

    一个更快的解决方案是将转换删除到 xml-document 并将其解析为纯文本。我仍然会避免Get-Content,因为它很慢。像这样的东西可以工作:

    # Get aboslute path
    $xmlpath = (Resolve-Path $filepath).Path
    
    # Get streamreader 
    $reader = [io.file]::OpenText($xmlpath)
    $currentroot = @()
    
    # Read every line
    while (($line = $reader.ReadLine()) -ne $null) {
        if ($line.Trim() -eq "<root>") {
            $currentroot.Clear()
            $currentroot += $line
        } else if ($line.Trim() -eq "</root>") {
            $currentroot += $line
    
            #process root element (by extracting the info from the strings in $currentroot)
    
            $currentroot.Clear()
        } else {
            $currentroot += $line
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2011-12-02
      • 2014-02-11
      • 2017-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-12
      • 1970-01-01
      相关资源
      最近更新 更多