简体   繁体   English

PowerShell - xpath 不区分大小写 XML 属性名称

[英]PowerShell - xpath for Case Insensitive XML attribute name

I have a XML where the attribute names can be combinations of lower-case and upper-case letters.我有一个 XML ,其中属性名称可以是小写和大写字母的组合。 In the below example, 'datasource' attribute can have any number of lowercase and uppercase letters.在下面的示例中,'datasource' 属性可以有任意数量的小写和大写字母。

I need to fetch those nodes where the 'datasource' is XML.我需要获取“数据源”为 XML 的那些节点。 I have searched all over the internet, but could not find any solution for this.我在整个互联网上进行了搜索,但找不到任何解决方案。 Several examples are there for translate(), lower-case() but they don't fit my scenario. 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

You could also use the case-insensitive dot notation like this:您还可以使用不区分大小写的点符号,如下所示:

$Nodes = $GM_ProcessXML.Process.Parameter | Where-Object { $_.DAtaSourcE -eq 'xML' }

This will return an array of System.Xml.XmlElement nodes这将返回System.Xml.XmlElement节点数组

Short of modifying the files:缺少修改文件:

[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

  • There is no case-insensitive string comparison in XPath 1.0 XPath 1.0 中没有不区分大小写的字符串比较
  • XPath 1.0 is all that is available in .NET XPath 1.0 是 .NET 中可用的全部
  • PowerShell is based completely on .NET PowerShell 完全基于 .NET

So, on the face of it, you are out of luck.所以,从表面上看,你运气不好。 But there is a work-around by combining PowerShell code and XPath translate() .但是通过结合 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)

Of course you can write the translate function by hand, especially in cases where the string to translate is basically hard-coded.当然,您可以手动编写翻译 function,尤其是在要翻译的字符串基本上是硬编码的情况下。

But this approach is generic, so you can also use it to search case-insensitively for any user-provided/dynamic value, eg:但是这种方法是通用的,因此您也可以使用它不区分大小写地搜索任何用户提供的/动态值,例如:

$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']

This is a lot better than the often-proposed这比经常提出的要好得多

translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')

since that is limited to pre-defined alphabets, and fails for eg accented characters unless you explicitly include them, which quickly becomes unwieldy.因为这仅限于预定义的字母,并且除非您明确包含重音字符,否则它会失败,这很快就会变得笨拙。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM