Reputation: 264
I have a XML where the attribute names can be combinations of lower-case and upper-case letters. In the below example, 'datasource' attribute can have any number of lowercase and uppercase letters.
I need to fetch those nodes where the 'datasource' is 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.
[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
Upvotes: 0
Views: 969
Reputation: 27408
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
Upvotes: 0
Reputation: 338108
So, on the face of it, you are out of luck. But there is a work-around by combining PowerShell code and 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.
But this approach is generic, so you can also use it to search case-insensitively for any user-provided/dynamic value, e.g.:
$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 e.g. accented characters unless you explicitly include them, which quickly becomes unwieldy.
Upvotes: 0
Reputation: 61013
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
Upvotes: 1