Get children and subchildren together? - xpath

I am using lxml library in python and I am working with xpath.I have a an xml file example as follows:
<Root>
<Child1 name="child1">
<Child2 name="child2" />
</Child1>
<Child3 name="child3">
<Child4 name="child4" />
</Child3>
<Child5 name="child5" />
</Root>
i need to know if there is a way to get all children at once like child1,child2,child3,child4 at once... currently I am able to get only child1, child3, child5 using root.xpath('node()')

Related

Mule 3.9 - Unable to fetch xml value using foreach of Xpath3 NODESET

I am unable to retrieve the XML values using the below code snippet in Mule 3.9.5 and it works with the lower versions. I am looking for the solutions in XPath using foreach only not splitter as per my use-case.
Mule flow XML
<foreach collection="#[xpath3('/ParentData/Data', payload, 'NODESET')]">
Sample XML
<ParentData>
<Data>
<test1>value1</test1>
<test2>value2</test2>
</Data>
<Data>
<test1>value1</test1>
<test2>value2</test2>
</Data>
</ParentData>
Actual Output
[]
Expected Output
<Data>
<test1>value1</test1>
<test2>value2</test2>
</Data>
<Data>
<test1>value1</test1>
<test2>value2</test2>
</Data>
Any suggestions ?
Using xpath3() returns a list of nodes of the XML implemented with Java class net.sf.saxon.dom.DOMNodeList. For some reason it doesn't print the details of each node in a <logger>.
I think it is clearer, more intuitive, better documented and portable to future versions of Mule to use DataWeave script instead.
Example:
<dw:transform-message doc:name="Transform Message">
<dw:input-payload mimeType="application/xml" />
<dw:set-variable variableName="data"><![CDATA[
%dw 1.0
%output application/java
---
payload.ParentData.*Data
]]>
</dw:set-variable>
</dw:transform-message>
<foreach collection="#[flowVars.data]" doc:name="For Each">
<logger message="Data=#[payload]" level="INFO" doc:name="Logger"/>
</foreach>
Output:
Data={test1=value1, test2=value2}
Data={test1=value1, test2=value2}
In Mule 4 you can use the DataWeave expression directly in the <foreach>.

Power Automate - Cloud Flow - Using xpath for parent node attributes

A RESTful API call returns the XML noted below.
I need to loop through various steps for each ShowSurveyAnswerKey. So in this case, 8 of them. Got that working with an "Apply to each" step expression of:
xpath(xml(body('HTTP_Get')),'//ShowSurveyAnswer')
In that "Apply to each", need to know values of ShowSurveyKey, ShowSurveyQuestionKey and ShowSurveyAnswerKey. The only one I can get working is ShowSurveyAnswerKey, which I happen to be testing with an action "Compose" with expression of:
xpath(item(),'string(/ShowSurveyAnswer/#ShowSurveyAnswerKey)')
So really, I can't figure out the parent or ancestor or ../ within Power Automate Compose Expression within the "Apply to each".
All help much appreciated. Thanks!
<?xml version="1.0" encoding="utf-8"?>
<Show ShowKey="123" >
<ShowSurveys>
<ShowSurvey ShowSurveyKey="230151" >
<SurveyQuestions>
<SurveyQuestion ShowSurveyQuestionKey="842125" >
<SurveyAnswers>
<ShowSurveyAnswer ShowSurveyAnswerKey="3316719" />
<ShowSurveyAnswer ShowSurveyAnswerKey="3316720" />
<ShowSurveyAnswer ShowSurveyAnswerKey="3316721" />
</SurveyAnswers>
</SurveyQuestion>
</SurveyQuestions>
</ShowSurvey>
<ShowSurvey ShowSurveyKey="217418" >
<SurveyQuestions>
<SurveyQuestion ShowSurveyQuestionKey="808668" >
<SurveyAnswers>
<ShowSurveyAnswer ShowSurveyAnswerKey="3192170" />
<ShowSurveyAnswer ShowSurveyAnswerKey="3192174" />
</SurveyAnswers>
</SurveyQuestion>
<SurveyQuestion ShowSurveyQuestionKey="808669" >
<SurveyAnswers>
<ShowSurveyAnswer ShowSurveyAnswerKey="3192175" />
<ShowSurveyAnswer ShowSurveyAnswerKey="3192176" />
<ShowSurveyAnswer ShowSurveyAnswerKey="3192177" />
</SurveyAnswers>
</SurveyQuestion>
</SurveyQuestions>
</ShowSurvey>
</ShowSurveys>
</Show>

Freeswitch use mod_lcr with originate api

Is there a way to use mod_lcr with originate command?
I want to originate a call and have mod_lcr decide which gateway should be used based on lcr rules (cost, reliability, etc).
When mod_lcr is used in the dialplan it will populate a variable ${lcr_auto_route} with the dialstring. How can I use the same logic with originate?
Thank you.
Here is how I did it.
I connect to freeswitch via ESL and execute the command
lcr 1716 default as xml
where 1716 is the digit sequence and default is the profile name (you can replace default with your own profile name)
Note 'as xml' will return an XML response. The response looks like this:
<result>
<row id="1">
<prefix>1716</prefix>
<carrier_name>carrier1</carrier_name>
<rate>0.15000</rate>
<codec></codec>
<cid></cid>
<limit></limit>
<dialstring>[lcr_carrier=carrier1,lcr_rate=0.15000]sofia/gateway/carrier1/1716</dialstring>
<event>
<headers>
<Event-Name>REQUEST_PARAMS</Event-Name>
<Core-UUID>151c590b-cce8-4eb3-b3ae-f48bad397870</Core-UUID>
<FreeSWITCH-Hostname>freeswitch</FreeSWITCH-Hostname>
<FreeSWITCH-Switchname>freeswitch</FreeSWITCH-Switchname>
<FreeSWITCH-IPv4>172.16.124.130</FreeSWITCH-IPv4>
<FreeSWITCH-IPv6>%3A%3A1</FreeSWITCH-IPv6>
<Event-Date-Local>2018-02-20%2007%3A33%3A42</Event-Date-Local>
<Event-Date-GMT>Tue,%2020%20Feb%202018%2006%3A33%3A42%20GMT</Event-Date-GMT>
<Event-Date-Timestamp>1519108422660002</Event-Date-Timestamp>
<Event-Calling-File>mod_lcr.c</Event-Calling-File>
<Event-Calling-Function>route_add_callback</Event-Calling-Function>
<Event-Calling-Line-Number>633</Event-Calling-Line-Number>
<Event-Sequence>786</Event-Sequence>
<lcr_digits>1716</lcr_digits>
<lcr_carrier_name>carrier1</lcr_carrier_name>
<lcr_rate_field>0.15000</lcr_rate_field>
<lcr_gw_prefix>sofia/gateway/carrier1/</lcr_gw_prefix>
<lcr_lead_strip>0</lcr_lead_strip>
<lcr_trail_strip>0</lcr_trail_strip>
</headers>
</event>
</row>
<row id="2">
<prefix>1</prefix>
<carrier_name>carrier2</carrier_name>
<rate>0.12000</rate>
<codec></codec>
<cid></cid>
<limit></limit>
<dialstring>[lcr_carrier=carrier2,lcr_rate=0.12000]sofia/external/0716#proxy.carrier2.net:5060</dialstring>
<event>
<headers>
<Event-Name>REQUEST_PARAMS</Event-Name>
<Core-UUID>151c590b-cce8-4eb3-b3ae-f48bad397870</Core-UUID>
<FreeSWITCH-Hostname>freeswitch</FreeSWITCH-Hostname>
<FreeSWITCH-Switchname>freeswitch</FreeSWITCH-Switchname>
<FreeSWITCH-IPv4>172.16.124.130</FreeSWITCH-IPv4>
<FreeSWITCH-IPv6>%3A%3A1</FreeSWITCH-IPv6>
<Event-Date-Local>2018-02-20%2007%3A33%3A42</Event-Date-Local>
<Event-Date-GMT>Tue,%2020%20Feb%202018%2006%3A33%3A42%20GMT</Event-Date-GMT>
<Event-Date-Timestamp>1519108422660002</Event-Date-Timestamp>
<Event-Calling-File>mod_lcr.c</Event-Calling-File>
<Event-Calling-Function>route_add_callback</Event-Calling-Function>
<Event-Calling-Line-Number>633</Event-Calling-Line-Number>
<Event-Sequence>787</Event-Sequence>
<lcr_digits>1</lcr_digits>
<lcr_carrier_name>carrier2</lcr_carrier_name>
<lcr_rate_field>0.12000</lcr_rate_field>
<lcr_gw_prefix>sofia/external/</lcr_gw_prefix>
<lcr_gw_suffix>%40proxy.carrier2.net%3A5060</lcr_gw_suffix>
<lcr_lead_strip>1</lcr_lead_strip>
<lcr_trail_strip>0</lcr_trail_strip>
<lcr_prefix>0</lcr_prefix>
</headers>
</event>
</row>
</result>
Then I parse the XML and grab the dialstring which is in this case
<dialstring>[lcr_carrier=carrier1,lcr_rate=0.15000]sofia/gateway/carrier1/1716</dialstring>
Then I use the dialstring (with some extra variables) in my originate command.

Replacing a content of a XML Tag [duplicate]

I'm trying to figure out how to open an xml file, search by an id, replace a value in the node and then resave the document.
my xml
<?xml version="1.0"?>
<data>
<user id="1370018670618">
<email>1#1.com</email>
<sent>false</sent>
</user>
<user id="1370018701357">
<email>2#2.com</email>
<sent>false</sent>
</user>
<user id="1370018769724">
<email>3#3.com</email>
<sent>false</sent>
</user>
<user id="1370028546850">
<email>4#4.com</email>
<sent>false</sent>
</user>
<user id="1370028588345">
<email>5#5.com</email>
<sent>false</sent>
</user>
</data>
My code to open and find a node
xml_content = File.read("/home/mike/app/users.xml")
doc = Nokogiri::XML(xml_content)
node_update = doc.search("//user[#id='1370028588345'] //sent")
node_update.inner_html ##returns value of "sent"
the part in this where I'm stuck is actually updating the node. node_update.inner_html = "true" returns a method error on inner_html. then after that saving the updated file.
First of all, your node_update is actually a NodeSet, not the Node that you probably think it is. You need a Node if you want to call inner_html= on it:
node_update[0].inner_html = 'true'
Then writing out the updated XML is just a bit of standard file manipulating combined with a to_xml call:
File.open('whatever.xml', 'w') { |f| f.print(doc.to_xml) }
As an aside, your input isn't valid XML. You have a </details> but no <details>.

Wix - How to remove the parent set of nodes using XmlConfig and Xpath

How do i find a text() node in XmlConfig and use it to remove the parent nodeset. All the examples I have seen just find and remove the 'found' node not the parent nodes.
My understanding is that this Xpath finds the matching node via verify path and ElementPath is the path of the nodes to remove. However Its not working at all.
Is text() supported?, I have tried [[*='ATrigger'[]], [[].='ATrigger'[]] but still no luck.
<util:XmlConfig Id="RemoveATriggerCompletely" File="[#QuartzXmlJob]" Sequence="104" Action="delete" On ="install" Node="element"
ElementPath="//job-scheduling-data/schedule/"
VerifyPath="//job-scheduling-data/schedule/trigger/cron/name[\[]text()='ATrigger'[\]]"/>
Given the following XML
<job-scheduling-data xmlns="http://quartznet.sourceforge.net/JobSchedulingData" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0">
<schedule>
<trigger>
<cron>
<name>ATrigger</name>
<group>default</group>
<description>Every 2 minutes</description>
<job-name>ATriggerJob</job-name>
<job-group>defaultGroup</job-group>
<misfire-instruction>SmartPolicy</misfire-instruction>
<!-- every 5mins -->
<cron-expression>2 * * * * ?</cron-expression>
</cron>
</trigger>
<trigger>
<cron>
<name>BTrigger</name>
<group>default</group>
<description>Every 2 minutes</description>
<job-name>BTriggerJob</job-name>
<job-group>defaultGroup</job-group>
<misfire-instruction>SmartPolicy</misfire-instruction>
<!-- every 5mins -->
<cron-expression>2 * * * * ?</cron-expression>
</cron>
</trigger>
The output i require is
<job-scheduling-data xmlns="http://quartznet.sourceforge.net/JobSchedulingData" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0">
<schedule>
<trigger>
<cron>
<name>BTrigger</name>
<group>default</group>
<description>Every 2 minutes</description>
<job-name>BTriggerJob</job-name>
<job-group>defaultGroup</job-group>
<misfire-instruction>SmartPolicy</misfire-instruction>
<!-- every 5mins -->
<cron-expression>2 * * * * ?</cron-expression>
</cron>
</trigger>
I have been banging my head against a wall for hours now so any help whatsoever is very much appreciated.
I'm not familiar with that "XmlConfig" task.
But I see two issues.
You need to alias the namespace and use that alias for the xpath "select".
I show the XmlPeek version below. Note I use "peanut", you can use any alias name you want.
Note the query now has "peanut:" in all the element names.
<!-- you do not need a namespace for this example, but I left it in for future reference -->
<XmlPeek Namespaces="<Namespace Prefix='peanut' Uri='http://quartznet.sourceforge.net/JobSchedulingData'/>"
XmlInputPath=".\Parameters.xml"
Query="//peanut:job-scheduling-data/peanut:schedule/peanut:trigger/peanut:cron/peanut:name[text()='ATrigger']/../..">
<Output TaskParameter="Result" ItemName="Peeked" />
</XmlPeek>
Note my "../.."
Once you find the correct element, finding its parent(s) is simple as the ".." notation.
You'll need to figure out how to add the namespace and alias to your Task (XmlConfig)
APPEND:
http://sourceforge.net/p/wix/bugs/2384/
Hmmm...dealing with a namespace isn't trivial. I think you're having a similar issue to what is reported there.
APPEND:
"Inline" Namespacing ... (Yuck)
<XmlPeek
XmlInputPath=".\Parameters.xml"
Query="//*[local-name()='job-scheduling-data' and namespace-uri()='http://quartznet.sourceforge.net/JobSchedulingData']/*[local-name()='schedule' and namespace-uri()='http://quartznet.sourceforge.net/JobSchedulingData']/*[local-name()='trigger' and namespace-uri()='http://quartznet.sourceforge.net/JobSchedulingData']/*[local-name()='cron' and namespace-uri()='http://quartznet.sourceforge.net/JobSchedulingData']/*[local-name()='name' and namespace-uri()='http://quartznet.sourceforge.net/JobSchedulingData'][text()='ATrigger']/../..">
<Output TaskParameter="Result" ItemName="Peeked" />
</XmlPeek>
Aka, try this Xpath:
"//*[local-name()='job-scheduling-data' and namespace-uri()='http://quartznet.sourceforge.net/JobSchedulingData']/*[local-name()='schedule' and namespace-uri()='http://quartznet.sourceforge.net/JobSchedulingData']/*[local-name()='trigger' and namespace-uri()='http://quartznet.sourceforge.net/JobSchedulingData']/*[local-name()='cron' and namespace-uri()='http://quartznet.sourceforge.net/JobSchedulingData']/*[local-name()='name' and namespace-uri()='http://quartznet.sourceforge.net/JobSchedulingData'][text()='ATrigger']/../.."

Resources