0

XML ドキュメントをロードし、実行してから、XML を文字列としてテーブルに挿入するコードが$xmlDoc.SelectNodes($XPath)ありforeach($node in $nodes)ます。

このコードは、ca のファイルで正常に動作します。10 レコードで 100KB。

ただし、ca のファイルがあります。100MBと約。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>
4

2 に答える 2

2

このリンクをベースとして使用して、以下のコードを試してください。ルート$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+= $_
  }
 }
于 2013-03-08T11:14:19.097 に答える
1

私の知る限り、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
    }
}
于 2013-03-08T10:33:45.413 に答える