I have a parser that gets xml values using xpath and transforms it to a json file. I am trying to do some xpath and make it relative but can only get it working if I make it static(absolute).
translate(ns2:ModelYear, translate(ns2:ModelYear,'0123456789',''), '')"
and I set it as false for IsStaticPath, but that doesn't work, however it does work if I do:
translate(/SOAP-ENV:Envelope/SOAP-ENV:Body/ns4:ProcessMessageResponse/ns4:payload/ns4:content/ns2:ShowVehicleInvoice/ns2:ShowVehicleInvoiceDataArea/ns2:VehicleInvoice/ns2:Invoice/ns2:VehicleInvoiceVehicleLineItem/ns2:Vehicle/ns2:ModelYear, translate(/SOAP-ENV:Envelope/SOAP-ENV:Body/ns4:ProcessMessageResponse/ns4:payload/ns4:content/ns2:ShowVehicleInvoice/ns2:ShowVehicleInvoiceDataArea/ns2:VehicleInvoice/ns2:Invoice/ns2:VehicleInvoiceVehicleLineItem/ns2:Vehicle/ns2:ModelYear,'0123456789',''), '')"
and I set IsStaticPath to true, but I dont want to do that. Any ideas? Not sure if my xpath is wrong or my parser needs some fixing.
Related
I have a certain XPATH-query which I use to get the height from a certain HTML-element which returns me perfectly the desired value when I execute it in Chrome via the XPath Helper-plugin.
//*/div[#class="BarChart"]/*[name()="svg"]/*[name()="svg"]/*[name()="g"]/*[name()="rect" and #class="bar bar1"]/#height
However, when I use the same query via the Get Element Attribute-keyword in the Robot Framework
Get Element Attribute//*/div[#class="BarChart"]/*[name()="svg"]/*[name()="svg"]/*[name()="g"]/*[name()="rect" and #class="bar bar1"]/#height
... then I got an InvalidSelectorException about this XPATH.
InvalidSelectorException: Message: u'invalid selector: Unable to locate an
element with the xpath expression `//*/div[#class="BarChart"]/*[name()="svg"]/*
[name()="svg"]/*[name()="g"]/*[name()="rect" and #class="bar bar1"]/`
So, the Robot Framework or Selenium removed the #-sign and everything after it. I thought it was an escape -problem and added and removed some slashes before the #height, but unsuccessful. I also tried to encapsulate the result of this query in the string()-command but this was also unsuccessful.
Does somebody has an idea to prevent my XPATH-query from getting broken?
It looks like you can't include the attribute axis in the XPath itself when you're using Robot. You need to retrieve the element by XPath, and then specify the attribute name outside that. It seems like the syntax is something like this:
Get Element Attribute xpath=(//*/div[#class="BarChart"]/*[name()="svg"]/*[name()="svg"]/*[name()="g"]/*[name()="rect" and #class="bar bar1"])#height
or perhaps (I've never used Robot):
Get Element Attribute xpath=(//*/div[#class="BarChart"]/*[name()="svg"]/*[name()="svg"]/*[name()="g"]/*[name()="rect" and #class="bar bar1"])[1]#height
This documentation says
attribute_locator consists of element locator followed by an # sign and attribute name, for example "element_id#class".
so I think what I've posted above is on the right track.
You are correct in your observation that the keyword seems to removes everything after the final #. More correctly, it uses the # to separate the element locator from the attribute name, and does this by splitting the string at that final # character.
No amount of escaping will solve the problem as the code isn't doing any parsing at this point. This is the exact code (as of this writing...) that performs that operation:
def _parse_attribute_locator(self, attribute_locator):
parts = attribute_locator.rpartition('#')
...
The simple solution is to drop that trailing slash, so your xpath will look like this:
//*/div[#class="BarChart"]/... and #class="bar bar1"]#height`
I'm attempting to use the tokenize method in a SelectNodes(" ") call, to filter some things out.
I have something along the lines of:
<nodes>
<node colors="RED,BLUE,YELLOW"/>
</nodes>
And my xpath is as such:
nodes/node[not(empty(tokenize("GREEN,YELLOW,PURPLE", ",") intersect tokenize(#colors, ",")))]
Simply, I've got two comma delimited list, one as an attribute, and one as a "filter" for the attributes. I want to select all nodes where #colors contains, somewhere, one of the words inside of "GREEN,YELLOW,PURPLE".
I thought I had the solution for it with that XPath, but it seems either:
A: I did something wrong, or
B: The version of XML DOM document I am using does not support tokenize()
The XPath above, in a SelectNodes( ) call will throw up an error message, saying msxml3.dll: Unknown method.", then pointing to the tokenize() method.
I tried doing setProperty("SelectionLanguage", "XPath"), but that did not seem to solve the issue either.
Is there any way for me to perform an equivalent XPath selection, without resorting to a bunch of and contains(#colors, "GREEN") and contains(#colors, "YELLOW")...?
As JLRishe says, msxml does not support XPath 2.0.
Depending on the environment that you are in there is probably third-party software you can use that supports either XPath 2.0 or XQuery 1.0 (which is a superset of XPath 2.0).
Microsoft's XML software is getting very dated and there has been little new development for 10 years now. It's time to consider alternatives.
How would I test for the following expression in Selenium?
not(//select[#id='ddlCountry']/#class) or
not(contains(//select[#id='ddlCountry']/#class,'invalidValue'))
true if the class attribute doesnt exist, or if it does, the attribute doesn't contain invalidValue.
I've tried using the verifyElementPresent command, but it errors out, I assume because I'm returning a boolean rather than a node.
I'm happy with an alternative to this if theres no way to do the above using xPath.
In case your XPath engine API doesnt allow expressions returning atomic values (not nodes), then you still can
Use:
//select[#id='ddlCountry'][contains(#class,'invalidValue')]
and test if an element was selected or not.
true if the class attribute doesnt
exist, or if it does, the attribute
doesn't contain invalidValue.
not(//select[#id='ddlCountry']/#class[contains(.,'invalidValue')])
I'm not very familiar with xpath. But I was working with xpath expressions and setting them in a database. Actually it's just the BAM tool for biztalk.
Anyway, I have an xml which could look like:
<File>
<Element1>element1<Element1>
<Element2>element2<Element2>
<Element3>
<SubElement>sub1</SubElement>
<SubElement>sub2</SubElement>
<SubElement>sub3</SubElement>
<Element3>
</File>
I was wondering if there is a way to use an xpath expression of getting all the SubElements concatted? At the moment, I am using:
/*[local-name()='File']/*[local-name()='Element3']/*[local-name()='SubElement']
This works if it only has one index. But apparently my xml sometimes has more nodes, so it gives NULL. I could just use
/*[local-name()='File']/*[local-name()='Element3']/*[local-name()='SubElement'][0]
but I need all the nodes. Is there a way to do this?
Thanks a lot!
Edit: I changed the XML, I was wrong, it's different, it should look like this:
<item>
<element1>el1</element1>
<element2>el2</element2>
<element3>el3</element3>
<element4>
<subEl1>subel1a</subEl1>
<subEl2>subel2a</subEl2>
</element4>
<element4>
<subEl1>subel1b</subEl1>
<subEl2>subel2b</subEl2>
</element4>
</item>
And I need to have a one line code to get a result like: "subel2a subel2b";
I need the one line because I set this xpath expression as an xml attribute (not my choice, it's specified). I tried string-join but it's not really working.
string-join(/file/Element3/SubElement, ',')
/File/Element3/SubElement will match all of the SubElement elements in your sample XML. What are you using to evaluate it?
If your evaluation method is subject to the "first node rule", then it will only match the first one. If you are using a method that returns a nodeset, then it will return all of them.
You can get all SubElements by using:
//SubElement
But this won't keep them grouped together how you want. You will want to do a query for all elements that contain a SubElement (basically do a search for the parent of any SubElements).
//parent::SubElement
Once you have that, you could (depending on your programming language) loop through the parents and concatenate the SubElements.
For example, I'm trying to pick out the value "Application Library" from the following XML - ie, the value under content-node/localedata/title, where localedata#locale = "en".
<content-node objectid="6_NO2UF4I1186E1026H4BLVI08F1">
<localedata locale="de">
<title>Anwendungsbibliothek</title>
</localedata>
<localedata locale="en">
<title>Application Library</title>
</localedata>
<localedata locale="es">
<title>Biblioteca de aplicaciones</title>
</localedata>
</content-node>
Specifically, what XPath expression do I put in the xsl:template#match value? I think it should be something like this, except I don't know how to match for the hardcoded value "en":
<xsl:template match="localedata[#locale = en]">
Am I on the right track here, or is there some other way I should go about this?
I would say yes, you should be on the right track. I can't seem to find any samples to verify and confirm this - but you should have no trouble trying and verifying this.
I say : go for it!
Looks like you'll have to adapt your XSL just a tiny bit:
<xsl:template match="localedata[#locale='en']">
With this (remove spaces after #locale, put the value in ' ... ') everything should be fine.
Marc