简体   繁体   中英

Identifying a particular node in XML using PowerShell

I am working with an XML document and I am not sure how to parse it to find a particular node.

In the example below I'd be searching for the ProductB and expecting to identify the Bee Hive

<PRODUCTS>
    <PRODUCT_LEVEL_1>
        <PRODUCT_ID>ProductA</PRODUCT_ID>
        <PRODUCT_NAME>Ant Hill</PRODUCT_NAME>
        <PRODUCT_ID>ProductB</PRODUCT_ID>
        <PRODUCT_NAME>Bee Hive</PRODUCT_NAME>
        <PRODUCT_ID>ProductC</PRODUCT_ID>
        <PRODUCT_NAME>Centipede Hotel</PRODUCT_NAME>
    </PRODUCT_LEVEL_1>
</PRODUCTS>

I'm not even sure how to refer to this format of XML which is making it difficult to search for.

Any assistance gratefully received.

Edit: At present I am loading the XML from a file using the following:

System.Xml.XmlDocument] $xd = new-object System.Xml.XmlDocument
$file = resolve-path($inputFile)
$xd.load($file)
$nodelist = $xd.selectnodes("/PRODUCTS/PRODUCT_LEVEL_1")
foreach ($documentNode in $nodelist) {
    #do some stuff
}

The actual XML file has loads of other junk in too but I stripped it out in the hopes of focusing on the bits I need. Perhaps I have stripped too much and the context has been lost?

You can use XPath for this task. XPath have axes, which allows you to refer preceding and following elements of document:

filter Prepare-StringForXPath {
    param(
        [Parameter(ValueFromPipeline)]
        [String]$String
    )
    if($String -notlike '*''*') {
        "'$String'"
    } elseif($String -notlike '*"*') {
        """$String"""
    } else {
        “concat($(($String -split '(?<=''[^"]*)(?=")|(?<="[^'']*)(?='')' | Prepare-StringForXPath) -join ', '))”
    }
}

$xd = [Xml]@'
<PRODUCTS>
    <PRODUCT_LEVEL_1>
        <PRODUCT_ID>ProductA</PRODUCT_ID>
        <PRODUCT_NAME>Ant Hill</PRODUCT_NAME>
        <PRODUCT_ID>ProductB</PRODUCT_ID>
        <PRODUCT_NAME>Bee Hive</PRODUCT_NAME>
        <PRODUCT_ID>ProductC</PRODUCT_ID>
        <PRODUCT_NAME>Centipede Hotel</PRODUCT_NAME>
    </PRODUCT_LEVEL_1>
</PRODUCTS>
'@

$ProdName = Read-Host 'Input product name'
$ProdID = $xd.SelectSingleNode("//PRODUCT_NAME[.=$(Prepare-StringForXPath $ProdName)]/preceding-sibling::PRODUCT_ID[1]").InnerText
"Product ID for '$ProdName' is '$ProdID'."

$ProdID = Read-Host 'Input product ID'
$ProdName = $xd.SelectSingleNode("//PRODUCT_ID[.=$(Prepare-StringForXPath $ProdID)]/following-sibling::PRODUCT_NAME[1]").InnerText
"Product name for '$ProdID' is '$ProdName'."

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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