In this xml, i have to filter tag <controlTask>
id values which matches to my stringArray $myStringArray (using powershell)
if matches, traverse into it and find <myflow:eventBooster>
with event="start"
and replace script content with $startContent1
, and find event="end"
replace with $endContent1
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns:myflow="http://myflow.google.com" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="POC">
<thread id="JALSA_KUSHI_ONLY" name="JALSA ONLY" isFine="true" myflow:isOk="true">
<docprocess>My Doc Process</docprocess>
<extensionElements>
<myflow:historyLevel><![CDATA[audit]]></myflow:historyLevel>
</extensionElements>
<controlTask id="ReadDoc1" name="Read Doc" myflow:type="http">
<extensionElements>
<myflow:field name="rnhAsJson">
<myflow:string><![CDATA[true]]></myflow:string>
</myflow:field>
<myflow:eventBooster event="start" >
<myflow:scriptInfo scriptType="javascript" script=""use strict";var loaded={require:require,exports:{}};" />
</myflow:eventBooster>
<myflow:eventBooster event="end" >
<myflow:scriptInfo scriptType="javascript" script=""use strict";var loaded={require:require,exports:{}},pending={};function require(e,t){define(void 0,e,t)};" />
<myflow:field name="language">
<myflow:string><![CDATA[javascript]]></myflow:string>
</myflow:field>
</myflow:eventBooster>
</extensionElements>
</controlTask>
<JimmyGate id="MyWish" name="My own" />
<controlTask id="WriteDoc1" name="write task" myflow:type="http">
<extensionElements>
<myflow:field name="requestMethod">
<myflow:string><![CDATA[POST]]></myflow:string>
</myflow:field>
<myflow:eventBooster event="start" >
<myflow:scriptInfo scriptType="javascript" script=""use strict";" />
</myflow:eventBooster>
<myflow:eventBooster event="end" >
<myflow:scriptInfo scriptType="javascript" script=""use strict";var loaded={require:require}" />
</myflow:eventBooster>
</extensionElements>
</controlTask>
<JimmyGate id="sid-iquweiq-1uy1-8173eu-817e81ye" />
</thread>
</definitions>
I have controltaskId, but unable to traverse into it. But getting all the data matching with <controlTask>
, <myflow:eventBooster>
$xmldata =( Select-Xml -Path $location\xyz.xml -XPath / ).Node;
$controltaskId = $xmldata.definitions.thread.controlTask.GetAttribute("id");
can someone please help here
CodePudding user response:
Here is a possible solution:
$xmldata.definitions.thread.controlTask.Where{ $_.id -in $myStringArray }.ForEach{
$_.extensionElements.eventBooster.Where{ $_.event -eq 'start' }.ForEach{
$_.scriptInfo.script = $startContent1
}
$_.extensionElements.eventBooster.Where{ $_.event -eq 'end' }.ForEach{
$_.scriptInfo.script = $endContent1
}
}
$xmldata.definitions.thread.controlTask
gives us an array of allcontrolTask
elements. Similarly,$_.extensionElements.eventBooster
gives us an array of alleventBooster
elements from the currentextensionElements
. See member access enumeration for how this works.- Use PowerShell intrinsic method
.Where{}
for filtering of arrays (alternatively use theWhere-Object
command).- Applied to
.controlTask
, filter byid
attribute that is contained in$myStringArray
. - Applied to
.eventBooster
, filter for matchingevent
attribute.
- Applied to
- PowerShell's intrinsic method
.ForEach{}
is used to iterate over the filtered element (alternatively use theForEach-Object
command). The syntax of the intrinsic methods is more concise and they perform better than the command alternatives so I prefer them for processing data structures (and not output of other commands).
CodePudding user response:
Try following :
using assembly System
using assembly System.Linq
using assembly System.Xml.Linq
$inputFilename = "c:\temp\test.xml"
$outputFilename = "c:\temp\test1.xml"
$xDoc = [System.Xml.Linq.XDocument]::Load($inputFilename)
$root = [System.Xml.Linq.XElement]$xDoc.Root
#Write-Host "root = " $root
$ns = [System.Xml.Linq.XNamespace]$root.GetNamespaceOfPrefix("myflow")
$eventBoosters = $xDoc.Descendants($ns "eventBooster")
$starts = [System.Linq.Enumerable]::Where($eventBoosters, [Func[object,bool]]{ param($x) [string]$x.Attribute("event").Value -eq "start"})
foreach($start in $starts)
{
[System.Xml.Linq.XElement]$start.SetAttributeValue("event", '$startContent1')
}
$ends = [System.Linq.Enumerable]::Where($eventBoosters, [Func[object,bool]]{ param($x) [string]$x.Attribute("event").Value -eq "end"})
foreach($end in $ends)
{
[System.Xml.Linq.XElement]$end.SetAttributeValue("event", '$endContent1')
}
$xDoc.Save($outputFilename)