The simplest PSv3+ solution is to use PowerShell's built-in XML DOM support, which makes an XML document's nodes accessible as a hierarchy of objects with dot notation:
PS> ([xml] (Get-Content -Raw txtfile.txt)).CustomObject.fields.fullName
ActivityDate
ActivityDateTime
Guid
Description
Note how even though .fields
is an array - representing all child <fields>
elements of top-level element <CustomObject>
- .fullName
was directly applied to it and returned the values of child elements <fullName>
across all array elements (<field>
elements) as an array.
This ability to access a property on a collection and have it implicitly applied to the collection's elements, with the results getting collected in an array, is a generic PSv3+ feature called member enumeration.
As an alternative, consider using the Select-Xml
cmdlet (available in PSv2 too), which supports XPath queries that generally allow for more complex extraction logic (though not strictly needed here); Select-Xml
is a high-level wrapper around the [xml]
.NET type's .SelectNodes()
method.
The following is the equivalent of the solution above:
$namespaces = @{ ns="http://soap.force.com/2006/04/metadata" }
$xpathQuery = '/ns:CustomObject/ns:fields/ns:fullName'
(Select-Xml -LiteralPath txtfile.txt $xpathQuery -Namespace $namespaces).Node.InnerText
Note:
Unlike with dot notation, XML namespaces must be considered when using Select-Xml
.
Given that <CustomObject>
and all its descendants are in namespace xmlns
, identified via URI http://soap.force.com/2006/04/metadata
, you must:
- define this namespace in a hashtable you pass as the
-Namespace
argument
- Caveat: Default namespace
xmlns
is special in that it cannot be used as the key in the hashtable; instead, choose an arbitrary key name such as ns
, but be sure to use that chosen key name as the node-name prefix (see next point).
- prefix all node names in the XPath query with the namespace name followed by
:
; e.g., ns:CustomObject
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…