0
Follow
4
View

PowerShell XML find element that is an exact match

a251010547 注册会员
2023-01-26 11:35

Consider XPath's sibling, XSLT, to de-duplicate nodes using the Muenchian Method where the use of implements hash tables on the document for efficient processing. PowerShell can run XSLT 1.0 with .NET's XslCompiledTransform Class. Specifically, below stylesheet runs the Identity Transform to copy document as is, indexes all the underlying content of with dot notation, and keeps only the first unique instance and its content.

(save as .xsl, a special .xml file)


  
  

  

  
    
      
    
  

  


# Load the style sheet.
$xslt = New-Object System.Xml.Xsl.XslCompiledTransform;
$xslt.Load("C:\Path\To\style.xsl");

# Execute the transform and output the results to a file.
$xslt.Transform("C:\Path\To\input.xml", "C:\Path\To\output.xml");
cuiliang521 注册会员
2023-01-26 11:35

The following is by no means a robust solution, but it may be good enough for your use case:

  • Use .SelectNodes() with an XPath query based on the id attribute with to find all candidate elements matching the lookup element.

  • Among the candidate elements, find the one(s) that matches the full content of the lookup element, via the .OuterXml property; see below for assumptions and limitations.

# Sample document.
# Note that the two UninstallProgram elements differ by the  element value only.
[xml] $xmlDoc = @'


    Lighting Analysis for Revit 2023
    UninstallString -like *AdODIS*
    C:\ProgramData\Autodesk\ODIS\metadata
    C:\Program Files\Autodesk\AdODIS\V1\Installer.exe
    -i uninstall --trigger_point system -m [Task~Resource]\[Task~GUID]\bundleManifest.xml -x [Task~Resource]\[Task~GUID]\SetupRes\manifest.xsd -q


    DIFFERS
    UninstallString -like *AdODIS*
    C:\ProgramData\Autodesk\ODIS\metadata
    C:\Program Files\Autodesk\AdODIS\V1\Installer.exe
    -i uninstall --trigger_point system -m [Task~Resource]\[Task~GUID]\bundleManifest.xml -x [Task~Resource]\[Task~GUID]\SetupRes\manifest.xsd -q


'@

# A sample element to look for in the document.
# Note: The assumption is that its .OuterXml property has no incidental whitespace,
#       which is what using an [xml] cast does.
$elem = ([xml] '
Lighting Analysis for Revit 2023UninstallString -like *AdODIS*C:\ProgramData\Autodesk\ODIS\metadataC:\Program Files\Autodesk\AdODIS\V1\Installer.exe-i uninstall --trigger_point system -m [Task~Resource]\[Task~GUID]\bundleManifest.xml -x [Task~Resource]\[Task~GUID]\SetupRes\manifest.xsd -q
').DocumentElement

# Find all elements with the same ID using an XPath query, then
# compare each matching element's .OuterXml values to that of the lookup element.
$xmlDoc.
  SelectNodes(('//UninstallProgram[@id="{0}"]' -f $elem.id)).
  Where({ $_.OuterXml -ceq $elem.OuterXml })

The above finds only the first element, because - while both have the same id attribute and are therefore matched by the XPath query passed to .SelectNodes() - only the first's content, as reflected in the .OuterXml property value, matches that of the lookup element.

Assumptions:

  • Both the input document and the element to look up must be parsed with incidental whitespace removed; using an [xml] cast in PowerShell (to parse XML text into a System.Xml.XmlDocument instance) does that by default.

  • The targets element's attributes, child elements, and their attributes must be in the same order in the input document and the lookup element.

  • If XML namespaces are involved, more work is needed.

About the Author

Question Info

Publish Time
2023-01-26 11:35
Update Time
2023-01-26 11:35