Given the following XML:
<?xml version="1.0" encoding="UTF-8" ?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Header>
<WFContext xmlns="http://service.wellsfargo.com/entity/message/2003/" soapenv:actor="" soapenv:mustUnderstand="0">
<messageId>cci-sf-dev14.wellsfargo.com:425a9286:14998ac6245:-7e1e</messageId>
<sessionId>425a9286:14998ac6245:-7e1d</sessionId>
<sessionSequenceNumber>1</sessionSequenceNumber>
<creationTimestamp>2014-11-10T00:14:49.243-08:00</creationTimestamp>
<invokerId>cci-sf-dev14.wellsfargo.com</invokerId>
<activitySourceId>P7</activitySourceId>
<activitySourceIdType>FNC</activitySourceIdType>
<hostName>cci-sf-dev14.wellsfargo.com</hostName>
<billingAU>05426</billingAU>
<originatorId>287586861901211</originatorId>
<originatorIdType>ECN</originatorIdType>
<initiatorId>GTST0793</initiatorId>
<initiatorIdType>ACF2</initiatorIdType>
</WFContext>
</soapenv:Header>
<soapenv:Body>
<getCustomerInformation xmlns="http://service.wellsfargo.com/provider/ecpr/customerProfile/inquiry/getCustomerInformation/2012/05/">
<initiatorInformation xmlns="http://service.wellsfargo.com/provider/ecpr/shared/common/2011/11/">
<channelInfo>
<initiatorCompanyNbr xmlns="http://service.wellsfargo.com/entity/message/2003/">114</initiatorCompanyNbr>
</channelInfo>
</initiatorInformation>
<custNbr xmlns="http://service.wellsfargo.com/entity/party/2003/">287586861901211</custNbr>
<customerViewList xmlns="http://service.wellsfargo.com/provider/ecpr/customerProfile/inquiry/getCustomerInformationCommon/2012/05/">
<customerView>
<customerViewType>GENERAL_INFORMATION_201205</customerViewType>
<preferences>
<generalInformationPreferences201205 xmlns="http://service.wellsfargo.com/provider/ecpr/customerProfile/inquiry/common/2012/05/">
<formattedNameIndicator xmlns="">true</formattedNameIndicator>
<includeTaxCertificationIndicator xmlns="">true</includeTaxCertificationIndicator>
</generalInformationPreferences201205>
</preferences>
</customerView>
<customerView>
<customerViewType>SEGMENT_LIST</customerViewType>
</customerView>
<customerView>
<customerViewType>LIMITED_PROFILE_REQUIRED_DATA</customerViewType>
</customerView>
<customerView>
<customerViewType>INDIVIDUAL_CUSTOMER_GENERAL_INFORMATION_201205</customerViewType>
<preferences>
<individualGeneralInformationPreferences xmlns="http://service.wellsfargo.com/provider/ecpr/customerProfile/inquiry/common/2012/05/">
<includeMinorIndicator xmlns="">true</includeMinorIndicator>
</individualGeneralInformationPreferences>
</preferences>
</customerView>
</customerViewList>
</getCustomerInformation>
</soapenv:Body>
</soapenv:Envelope>
I am trying to access the getCustomerInformation tag using relative XPath in VBScript.
XMLDataFile = "C:\testReqfile.xml"
Set xmlDoc = XMLUtil.CreateXML()
xmlDoc.LoadFile(XMLDataFile)
Print xmlDoc.ToString
'xmlDoc.AddNamespace "ns","xmlns:soapenv=http://schemas.xmlsoap.org/soap/envelope/"
Set childrenObj = xmlDoc.ChildElementsByPath("//*[contains(#xmlns,'getCustomerInformation')]")
msgbox childrenObj.Count
But is failing to return a node.
Your XPath expression does not work because xmlns as in
<getCustomerInformation xmlns="http://service.wellsfargo.com/provider/ecpr/customerProfile/inquiry/getCustomerInformation/2012/05/">
is a default namespace, not an attribute. Therefore, it cannot be accessed with #xmlns.
But it seems you do not have to rely on the namespace at all, because the element name ("getCustomer Information") is telling already. To bypass the problem of those elements being in a namespace, use local-name() to select elements by their name.
Set childrenObj = xmlDoc.ChildElementsByPath("//*[local-name() = 'getCustomerInformation']")
As #Mathias Müller already explained in his answer, xmlns defines a namespace and can thus not be accessed like a regular attribute. I don't have experience with XmlUtil, but in standard VBScript you could select the node(s) like this:
Set xml = CreateObject("Msxml2.DOMDocument.6.0")
xml.async = False
xml.load "C:\path\to\your.xml"
If xml.ParseError Then
WScript.Echo xml.ParseError.Reason
WScript.Quit 1
End If
'define a namespace alias "ns"
uri = "http://service.wellsfargo.com/provider/ecpr/customerProfile/inquiry/getCustomerInformation/2012/05/"
xml.setProperty "SelectionNamespaces", "xmlns:ns='" & uri & "'"
'select nodes using the namespace alias
Set nodes = xml.SelectNodes("//ns:getCustomerInformation")
Related
I am making a SOAP webservice call and I get the below response. I want to read the value in internal XML, the value is 12345684 in 1234684 in the below XML.
I was able to get internal XML using #[xpath3('//:processaResponse /return[2]')], store it in a flow variable and #[xpath3('/AckReg/DataArea/PRegistration/PRDet/Person/IDSet/:ID[#schemeName="aid"]/text()')].
This works when I try an online parser, but it doesn't read the value in Mule.
Is there any way to extract 1234684 in oa:ID tag using one XPath.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<ns3:TXID xmlns:ns3="http://a.d.r.test.com/"></ns3:TXID>
<ns3:SESSIONID xmlns:ns3="http://a.d.r.test.com/"></ns3:SESSIONID>
</soapenv:Header>
<soapenv:Body>
<ns3:processaResponse xmlns:ns3="http://a.d.r.test.com/" xmlns:ns2="http://p.r.test.com/">
<return>Hi</return>
<return>
<?xml version="1.0" encoding="UTF-8"?>
<AckReg
xmlns="http://www.test.com/e/1" languageCode="en-US" releaseID="normalizedString" systemEnvironmentCode="test" versionID="normalizedString"
xmlns:oa="www.test.com/r/9"
xsi:schemaLocation="http://www.test.com/a/1 ../test/test.xsd">
<Apa>
<oa:CreationDateTime>2018-04-05</oa:CreationDateTime>
</Apa>
<DataArea>
<Ack>
<OArea>
<o:Sender>
<o:LID schemeAgencyName="testi" schemeName="Application ID">test</o:LID>
</o:Sender>
</OArea>
<OriginalActionVerb/>
</Ack>
<PRegistration>
<testids>
<IDSet schemeAgencyName="try">
<oa:ID schemeName="abcid">1234684</oa:ID>
</IDSet>
</testids>
<PRDet>
<Person>
<IDSet schemeAgencyName="try">
<oa:ID schemeName="aid">1364561</oa:ID>
</IDSet>
<IDSet schemeAgencyName="enada">
<oa:ID schemeName="Employee ID">adsad</oa:ID>
</IDSet>
</Person>
<User>
<oa:ID/>
</User>
</PRDet>
</PRegistration>
</DataArea>
</AckReg>
</return>
</ns3:processaResponse>
</soapenv:Body>
</soapenv:Envelope>
In your expressions you were missing namespace prefixes or namespace wildcards *: on some nodes - so your expressions failed.
Is there any way to extract 1234684 in oa:ID tag using one XPath.
Combining both of your partial expressions is possible with namespace wildcards:
//*:processaResponse/return[2]/*:AckReg/*:DataArea/*:PRegistration/*:testids/*:IDSet/*:ID[#schemeName='abcid']/text()
Or you can use an absolute path with namespace wildcards:
/*:Envelope/*:Body/*:processaResponse/return[2]/*:AckReg/*:DataArea/*:PRegistration/*:testids/*:IDSet/*:ID[#schemeName='abcid']/text()
Output in both cases:
1234684
You can even use XmlSlurper class using groovy script to fetch that respective value.
root = new XmlSlurper( false, true).parseText(payload).declareNamespace('soapenv':"http://schemas.xmlsoap.org/soap/envelope/")
I have questions about libxml-ruby.
There is a xml file "sample.xml".
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<worksheet xmlns="http://***" xmlns:r="http://???">
<sheetData>
<row><v>1</v></row>
</sheetData>
</worksheet>
I want to deal with nodes without specifying default namespace like below.
xml = XML::Document.file('sample.xml')
sheet_data = xml.find_first('sheetData')
Of course, I can do it like below.
NS = {
main: 'http://***',
r: 'http://???',
}
sheet_data = xml.find_first('main:sheetData', NS)
But I want to omit string of default namespace.
I tried some properties and methods belongs to XML::Namespace[s], but not effected.
And one more problem when I save a xml file.
ns = XML::Namespace.new(xml.root, 'main', 'http://***')
row = XML::Node.new('row', nil, ns)
sheet_data << row
xml.save("sample.xml")
Published like below.
<row><v>1</v></row>
<main:row/>
I want that it's omitted string of "main:".
So I do this, but it's really ugly.
open('sample.xml', 'wb') do |f|
f.write(xml.to_s.gsub(/(<\/?)main:/, '\1'))
end
Do you have any good idea?
I'm parsing a pptx file and ran into an issue. This is a sample of the source XML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<p:presentation xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
<p:sldMasterIdLst>
<p:sldMasterId id="2147483648" r:id="rId2"/>
</p:sldMasterIdLst>
<p:sldIdLst>
<p:sldId id="256" r:id="rId3"/>
</p:sldIdLst>
<p:sldSz cx="10080625" cy="7559675"/>
<p:notesSz cx="7772400" cy="10058400"/>
</p:presentation>
I need to to get the r:id attribute value in the sldMasterId tag.
doc = Nokogiri::XML(path_to_pptx)
doc.xpath('p:presentation/p:sldMasterIdLst/p:sldMasterId').attr('id').value
returns 2147483648 but I need rId2, which is the r:id attribute value.
I found the attribute_with_ns(name, namespace) method, but
doc.xpath('p:presentation/p:sldMasterIdLst/p:sldMasterId').attribute_with_ns('id', 'r')
returns nil.
You can reference the namespace of attributes in your xpath the same way you reference element namespaces:
doc.xpath('p:presentation/p:sldMasterIdLst/p:sldMasterId/#r:id')
If you want to use attribute_with_ns, you need to use the actual namespace, not just the prefix:
doc.at_xpath('p:presentation/p:sldMasterIdLst/p:sldMasterId')
.attribute_with_ns('id', "http://schemas.openxmlformats.org/officeDocument/2006/relationships")
http://nokogiri.org/Nokogiri/XML/Node.html#method-i-attributes
If you need to distinguish attributes with the same name, with different namespaces use attribute_nodes instead.
doc.xpath('p:presentation/p:sldMasterIdLst/p:sldMasterId').each do |element|
element.attribute_nodes().select do |node|
puts node if node.namespace && node.namespace.prefix == "r"
end
end
I am trying to down my last 3200 tweets in groups of 200(in multiple pages) using restclient gem.
In the process, I end up adding the following lines multiple times to my file:
</statuses>
<?xml version="1.0" encoding="UTF-8"?>
<statuses type="array">
To get this right(as the XML parsing goes for a toss), after downloading the file, I want to replace all occurrences of the above string except the first.
I am trying the following:
tweets_page = RestClient.get("#{GET_STATUSES_URL}&page=#{page_number}")
message = <<-MSG
</statuses>
<?xml version="1.0" encoding="UTF-8"?>
<statuses type="array">
MSG
unless page_number == 1
tweets_page.gsub!(message,"")
end
What is wrong in the above? Is there a better way to do the same?
I believe it would be faster to download the whole bunch at once and split the body of your response by message and add it for the first entry.
Something like this, can't try it out so consider this just as an idea.
tweets_page = RestClient.get("#{GET_STATUSES_URL}").body
tweets = tweets_page.split(message)
tweets_page = tweets[0]+message+tweets[1..-1]
You could easily break them up in groups of 200 like that also
If you want to do it with a gsub on the whole text you could use the following
tweets_page = <<-MSG
first
</statuses>
<?xml version="1.0" encoding="UTF-8"?>
<statuses type="array">
second
</statuses>
<?xml version="1.0" encoding="UTF-8"?>
<statuses type="array">
rest
MSG
message = <<-MSG
</statuses>
<?xml version="1.0" encoding="UTF-8"?>
<statuses type="array">
MSG
new_str = tweets_page.gsub message do |match|
if defined? #first
""
else
#first = true
message
end
end
p new_str
gives
type=\"array\">\nrest\n"
"first\n</statuses>\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<statuses type=\"array\">\nsecond\nrest\n"
I have an XML, which can be like
<?xml version="1.0" encoding="utf-8"?>
<testnode type="1">123</testnode>
or like
<?xml version="1.0" encoding="utf-8"?>
<othernode attrib="true">other value</othernode>
or the root node can be something completely unexpected. (Theoretically anything.)
I'm using REXML to parse it. How can I find out what XML node is the root element?
xml = REXML::Document.new "<?xml version" #etc (or load from file)
root_node = xml.elements[1]
root_node_name = root_node.name