PowerShell - 不区分大小写 XML 属性名称的 xpath
PowerShell - xpath for Case Insensitive XML attribute name
我有一个XML,其中属性名称可以是大小写字母的组合。
在下面的示例中,'datasource' 属性可以包含任意数量的小写和大写字母。
我需要获取 'datasource' 为 XML 的那些节点。
我在互联网上搜索过,但找不到任何解决方案。 translate()、lower-case() 有几个例子,但它们不适合我的场景。
[xml] $GM_ProcessXML =@'
<Process>
<Parameter Name="Parameter1" Datasource="XML"><![CDATA[Sujeet]]></Parameter>
<Parameter Name="Parameter2" DataSource="XML"><![CDATA[Padhi]]></Parameter>
<Parameter Name="Parameter3" DatASource="XML"><![CDATA[Padhi]]></Parameter>
<Parameter Name="Parameter4" datASource="XML"><![CDATA[Padhi]]></Parameter>
<Node>
<Node1 Name="Node1" Datasource="XML"><![CDATA[Sujeet]]></Node1>
<Node2 Name="Node2" DataSource="XML"><![CDATA[Padhi]]></Node2>
<Node3 Name="Node3" DatASource="XML"><![CDATA[Padhi]]></Node3>
<Node4 Name="Node4" datASource="XML"><![CDATA[Padhi]]></Node4>
</Node>
</Process>
'@
$XPath = "//*[@datasource='XML']"
$Nodes = $GM_ProcessXML.SelectNodes($XPath)
$Nodes
您也可以像这样使用不区分大小写的点符号:
$Nodes = $GM_ProcessXML.Process.Parameter | Where-Object { $_.DAtaSourcE -eq 'xML' }
这将 return 一个包含 System.Xml.XmlElement
个节点的数组
缺少修改文件:
[xml]$GM_ProcessXML = @'
<Process>
<Parameter Name="Parameter1" Datasource="XML"><![CDATA[Sujeet]]></Parameter>
<Parameter Name="Parameter2" DataSource="XML"><![CDATA[Padhi]]></Parameter>
<Parameter Name="Parameter3" DatASource="XML"><![CDATA[Padhi]]></Parameter>
<Parameter Name="Parameter4" datASource="XML"><![CDATA[Padhi]]></Parameter>
<Node>
<Node1 Name="Node1" Datasource="XML"><![CDATA[Sujeet]]></Node1>
<Node2 Name="Node2" DataSource="XML"><![CDATA[Padhi]]></Node2>
<Node3 Name="Node3" DatASource="XML"><![CDATA[Padhi]]></Node3>
<Node4 Name="Node4" datASource="XML"><![CDATA[Padhi]]></Node4>
</Node>
</Process>
'@ -replace 'datasource','datasource'
$XPath = "//*[@datasource='XML']"
$Nodes = $GM_ProcessXML.SelectNodes($XPath)
$Nodes
Name datasource #cdata-section
---- ---------- --------------
Parameter1 XML Sujeet
Parameter2 XML Padhi
Parameter3 XML Padhi
Parameter4 XML Padhi
Node1 XML Sujeet
Node2 XML Padhi
Node3 XML Padhi
Node4 XML Padhi
- XPath 1.0 中没有不区分大小写的字符串比较
- XPath 1.0 是 .NET 中可用的全部
- PowerShell 完全基于 .NET
所以,从表面上看,你运气不好。但是可以通过组合 PowerShell 代码和 XPath translate()
.
来解决问题
[xml] $GM_ProcessXML =@'
<Process>
<Parameter Name="Parameter1" Datasource="XML"><![CDATA[Sujeet]]></Parameter>
<Parameter Name="Parameter2" DataSource="XML"><![CDATA[Padhi]]></Parameter>
<Parameter Name="Parameter3" DatASource="XML"><![CDATA[Padhi]]></Parameter>
<Parameter Name="Parameter4" datASource="XML"><![CDATA[Padhi]]></Parameter>
<Node>
<Node1 Name="Node1" Datasource="XML"><![CDATA[Sujeet]]></Node1>
<Node2 Name="Node2" DataSource="XML"><![CDATA[Padhi]]></Node2>
<Node3 Name="Node3" DatASource="XML"><![CDATA[Padhi]]></Node3>
<Node4 Name="Node4" datASource="XML"><![CDATA[Padhi]]></Node4>
</Node>
</Process>
'@
$attributeName = 'DataSource'
$lc = $attributeName.ToLowerInvariant() # -> 'datasource'
$uc = $attributeName.ToUpperInvariant() # -> 'DATASOURCE'
$XPath = "//*[@*[translate(name(), '$uc', '$lc') = '$lc'] = 'XML']"
# -> //*[@*[translate(name(), 'DATASOURCE', 'datasource') = 'datasource'] = 'XML']
$Nodes = $GM_ProcessXML.SelectNodes($XPath)
当然你可以手写翻译函数,尤其是在翻译的字符串基本上是硬编码的情况下。
但这种方法是通用的,因此您也可以使用它来不区分大小写地搜索 any user-provided/dynamic 值,例如:
$value = 'sujeet' # as the user has entered it
$lc = $value.ToLowerInvariant()
$uc = $value.ToUpperInvariant()
$XPath = "//Parameter[translate(., '$uc', '$lc') = '$lc']"
# -> //Parameter[translate(., 'SUJEET', 'sujeet') = 'sujeet']
这比经常提出的
好很多
translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')
因为这仅限于预定义的字母表,并且对于例如除非您明确包含重音字符,否则很快就会变得笨拙。
我有一个XML,其中属性名称可以是大小写字母的组合。 在下面的示例中,'datasource' 属性可以包含任意数量的小写和大写字母。
我需要获取 'datasource' 为 XML 的那些节点。 我在互联网上搜索过,但找不到任何解决方案。 translate()、lower-case() 有几个例子,但它们不适合我的场景。
[xml] $GM_ProcessXML =@'
<Process>
<Parameter Name="Parameter1" Datasource="XML"><![CDATA[Sujeet]]></Parameter>
<Parameter Name="Parameter2" DataSource="XML"><![CDATA[Padhi]]></Parameter>
<Parameter Name="Parameter3" DatASource="XML"><![CDATA[Padhi]]></Parameter>
<Parameter Name="Parameter4" datASource="XML"><![CDATA[Padhi]]></Parameter>
<Node>
<Node1 Name="Node1" Datasource="XML"><![CDATA[Sujeet]]></Node1>
<Node2 Name="Node2" DataSource="XML"><![CDATA[Padhi]]></Node2>
<Node3 Name="Node3" DatASource="XML"><![CDATA[Padhi]]></Node3>
<Node4 Name="Node4" datASource="XML"><![CDATA[Padhi]]></Node4>
</Node>
</Process>
'@
$XPath = "//*[@datasource='XML']"
$Nodes = $GM_ProcessXML.SelectNodes($XPath)
$Nodes
您也可以像这样使用不区分大小写的点符号:
$Nodes = $GM_ProcessXML.Process.Parameter | Where-Object { $_.DAtaSourcE -eq 'xML' }
这将 return 一个包含 System.Xml.XmlElement
个节点的数组
缺少修改文件:
[xml]$GM_ProcessXML = @'
<Process>
<Parameter Name="Parameter1" Datasource="XML"><![CDATA[Sujeet]]></Parameter>
<Parameter Name="Parameter2" DataSource="XML"><![CDATA[Padhi]]></Parameter>
<Parameter Name="Parameter3" DatASource="XML"><![CDATA[Padhi]]></Parameter>
<Parameter Name="Parameter4" datASource="XML"><![CDATA[Padhi]]></Parameter>
<Node>
<Node1 Name="Node1" Datasource="XML"><![CDATA[Sujeet]]></Node1>
<Node2 Name="Node2" DataSource="XML"><![CDATA[Padhi]]></Node2>
<Node3 Name="Node3" DatASource="XML"><![CDATA[Padhi]]></Node3>
<Node4 Name="Node4" datASource="XML"><![CDATA[Padhi]]></Node4>
</Node>
</Process>
'@ -replace 'datasource','datasource'
$XPath = "//*[@datasource='XML']"
$Nodes = $GM_ProcessXML.SelectNodes($XPath)
$Nodes
Name datasource #cdata-section
---- ---------- --------------
Parameter1 XML Sujeet
Parameter2 XML Padhi
Parameter3 XML Padhi
Parameter4 XML Padhi
Node1 XML Sujeet
Node2 XML Padhi
Node3 XML Padhi
Node4 XML Padhi
- XPath 1.0 中没有不区分大小写的字符串比较
- XPath 1.0 是 .NET 中可用的全部
- PowerShell 完全基于 .NET
所以,从表面上看,你运气不好。但是可以通过组合 PowerShell 代码和 XPath translate()
.
[xml] $GM_ProcessXML =@'
<Process>
<Parameter Name="Parameter1" Datasource="XML"><![CDATA[Sujeet]]></Parameter>
<Parameter Name="Parameter2" DataSource="XML"><![CDATA[Padhi]]></Parameter>
<Parameter Name="Parameter3" DatASource="XML"><![CDATA[Padhi]]></Parameter>
<Parameter Name="Parameter4" datASource="XML"><![CDATA[Padhi]]></Parameter>
<Node>
<Node1 Name="Node1" Datasource="XML"><![CDATA[Sujeet]]></Node1>
<Node2 Name="Node2" DataSource="XML"><![CDATA[Padhi]]></Node2>
<Node3 Name="Node3" DatASource="XML"><![CDATA[Padhi]]></Node3>
<Node4 Name="Node4" datASource="XML"><![CDATA[Padhi]]></Node4>
</Node>
</Process>
'@
$attributeName = 'DataSource'
$lc = $attributeName.ToLowerInvariant() # -> 'datasource'
$uc = $attributeName.ToUpperInvariant() # -> 'DATASOURCE'
$XPath = "//*[@*[translate(name(), '$uc', '$lc') = '$lc'] = 'XML']"
# -> //*[@*[translate(name(), 'DATASOURCE', 'datasource') = 'datasource'] = 'XML']
$Nodes = $GM_ProcessXML.SelectNodes($XPath)
当然你可以手写翻译函数,尤其是在翻译的字符串基本上是硬编码的情况下。
但这种方法是通用的,因此您也可以使用它来不区分大小写地搜索 any user-provided/dynamic 值,例如:
$value = 'sujeet' # as the user has entered it
$lc = $value.ToLowerInvariant()
$uc = $value.ToUpperInvariant()
$XPath = "//Parameter[translate(., '$uc', '$lc') = '$lc']"
# -> //Parameter[translate(., 'SUJEET', 'sujeet') = 'sujeet']
这比经常提出的
好很多translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')
因为这仅限于预定义的字母表,并且对于例如除非您明确包含重音字符,否则很快就会变得笨拙。