Powershell 的设计非常松散,容易导致意外结果,操作 XML 时存在很多的坑。
假设 $Xml 是一个代表 XML 文档对象 System.Xml.XmlDocument 的变量,
- $Xml.PreserveWhitespace = $True
复制代码 保留多余的空白内容,如果没有设置为 $True,保存以后 XML 文档会删除这些不必要的空白内容。
Powershell 会做很多自动处理,如果不了解 Powershell 的转换机制去想当然地写代码,会被坑死。
以上写法在 Powershell 中有很多种潜在的可能表示。
第一种,它可以代表 foo 节点的 bar 属性- <foo bar="wuxiancheng"></foo>
复制代码 第二种,它可以代表 foo 节点的 bar 节点- <foo><bar>baz</bar></foo>
复制代码 第三种,如果 foo 节点有两个以上的 bar 节点,它代表的是所有的子节点,这时候它是一个由多个对象组成的数组。- <foo><bar></bar><bar></bar></foo>
复制代码 第四种,如果 foo 节点既有名称为 bar 的属性,也有节点名为 bar 的子节点,它代表的是属性和子节点,这时候它是一个由多个对象组成的数组。- <foo bar="wuxiancheng"><bar>baz</bar></foo>
复制代码 第五种,是第四种和第五种结合。- <foo bar="wuxiancheng"><bar>baz</bar><bar>baz</bar></foo>
复制代码 说了代表什么,还要说怎样代表。
如果 $Xml.foo.bar 成功取回了一个属性,那么它以字符串的形式返回这个属性的值,下述示例返回 wuxiancheng。- <foo bar="wuxiancheng"></foo>
复制代码 如果 $Xml.foo.bar 成功取回了一个节点,如果节点 bar 既没有任何属性,也没有任何除文本以外的子节点,那么它以字符串的形式返回节点 bar 的文本内容,下述示例返回 baz。- <foo><bar>baz</bar></foo>
复制代码 如果这个节点 bar 有一个以上的属性,或者有一个以上的非文本子节点,它以 XmlElement 对象返回节点 bar- <foo><bar baz="quax" /></foo>
复制代码 如果 $Xml.foo.bar 成功取回了两个以上的 bar 节点,或者成功取回了一个 bar 节点和一个 bar 属性,或者同时取到了两个以上的 bar 节点和一个 bar 属性,它以 Object[] 返回这些取到的对象。
因为 Powershell 会不动声色地做很多转换,为了避免发生意外,写代码时要尽量明确动机,清晰明确地指示 Powershell 做正确的事,操作属性就使用操作属性的方式,操作单一节点就使用单一节点的方式,操作节点集合就使用操作节点集合的方式,避免一套逻辑操作所有东西。
操作元素属性可以使用 XML 元素的这些方法- GetAttribute()
- SetAttribute()
- RemoveAttribute()
复制代码 要取回一个元素的所有属性,可以使用元素对象的以下属性,它是一个 System.Xml.XmlAttributeCollection 对象。要操作元素,可以使用这些方法- SelectSingleNode()
- SelectNodes()
复制代码 更多的信息以参考 .Net 文档。 |
|