Wil*_* YK 6 xml powershell element xmlelement
我有一个包含各种元素的 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
Run Code Online (Sandbox Code Playgroud)
原则上回顾一下您已经尝试过的操作:为了$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)
}
Run Code Online (Sandbox Code Playgroud)
至于你尝试过的:
$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
| 归档时间: |
|
| 查看次数: |
146 次 |
| 最近记录: |