我有一個包含各種元素的 XML,但其中一個名為RowId,我想移動到相應 XML 陣列的頂部...基本上以我的方式對元素進行排序。我下面的代碼可以復制/粘貼供您測驗。
實作這一目標的最佳方法是什么?和/或有比我現在正在做的更好的方法嗎?這看起來很笨拙。
如果我包含,為什么下面的代碼會起作用
| Sort-Object -Property "Name"?
復制并粘貼以下代碼:
$rawXML = [xml]@"
<?xml version="1.0" encoding="utf-8"?>
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Document">
<xs:complexType>
<xs:sequence>
<xs:element name="Object1" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="Element1" nillable="true">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="80"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="Element2" nillable="true">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="-1"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="RowId">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="20"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Object2" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="Element4" nillable="true">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="80"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="Element5" nillable="true">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="-1"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="RowId">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="20"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
"@
$rawXML.schema.element.complexType.sequence.element.complexType.sequence | ForEach-Object {
$sequence = $_
# This does NOT work
$childNodes = $sequence.ChildNodes #| Sort-Object -Property "Name"
$childNodes.Count # Output = 3
$sequence.RemoveAll()
$childNodes.Count # Output = 0
# This DOES work; Only difference is '| Sort-Object -Property "Name"'
<#
$childNodes = $sequence.ChildNodes | Sort-Object -Property "Name"
$childNodes.Count # Output = 3
$sequence.RemoveAll()
$childNodes.Count # Output = 3
#>
$childNodes | ForEach-Object {
$child = $_
if ($child.Name -eq "RowId") {
$sequence.InsertBefore($child, $sequence.FirstChild)
} else {
$sequence.AppendChild($child) | out-null
}
}
}
$rawXML.InnerXml
uj5u.com熱心網友回復:
回顧一下您原則上已經嘗試過的內容:為了修改$rawXML直接存盤在其中的 XML DOM ,您需要使用[xml]( System.Xml.XmlDocument) .NET 型別自己的方法。
下面的簡化方法首先定位感興趣的子元素,然后使用.InsertBefore()將其移動到頂部(插入之前不需要洗掉被移動的元素):
$rawXML.schema.element.complexType.sequence.element.complexType.sequence | ForEach-Object {
# Find the child element whose 'name' attribute is 'RowId'
$rowIdElem = $_.ChildNodes.Where({ $_.name -eq 'RowId' })[0]
# Insert the row-ID element before the currently first child element,
# which effectively moves it to the top.
$null = $_.InsertBefore($rowIdElem, $_.FirstChildNode)
}
至于你嘗試了什么:
$childNodes = $sequence.ChildNodes有效地$childNodes指向存盤在元素屬性中的子節點的實時串列.ChildNodes(它是從 派生的型別System.Xml.XmlNodeList)因此,打完電話后
$sequence.ChildNodes.Clear()洗掉所有子節點,都$sequence.ChildNodes和$childNodes參考一個空的集合,即有什么可列舉,這就是為什么ForEach-Object腳本塊($childNodes | ForEach-Object { ... })永遠不會被呼叫。相比之下,通過涉及
Sort-Object呼叫($childNodes = $sequence.ChildNode | Sort-Object Name),你列舉的子元素在那里,然后,和捕獲快照的子元素作為一個獨立的陣列(型別的常規PowerShell的陣列[object[]]),其元素是為以后預計列舉,導致按ForEach-Object自定義順序重新附加元素的呼叫按預期作業。
uj5u.com熱心網友回復:
我認為 DOM NodeLists 是正常 DOM 使用中的“實時”集合(“實時”我認為是 W3C 規范中的規范術語,Microsoft 檔案稱它們為動態:https : //docs.microsoft.com/en-us/dotnet /standard/data/xml/dynamic-updates-to-nodelists-and-namednodemaps),因此您嘗試$childNodes = $sequence.ChildNodes將活動 NodeList 存盤在一個變數中,并且作為一個集合,它反映了對 DOM 樹的任何更改。在PowerShell中使用管道是收集到的Sort-Object與$sequence.ChildNodes | Sort-Object -Property "Name"未回傳的XmlNodeList或其他帶電/動態集合,而是回傳一個物件,比如陣列XmlNode[]或者object[],這樣的方式你的代碼作業,你希望它的作業,你以后再處理該陣列而不是跟蹤 DOM 樹更改的 XmlNodeList。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/389418.html
上一篇:如何洗掉XML檔案的一部分?
下一篇:如何為這個xml創建一個xslt&輸出是帶有culomn{numInscription,nom,prenom,nomModule}&條件etudiant.id_promo=module.id_prom
