How can I use XSL to run a template against a specific node that is located by an attribute? - xpath

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

Related

Can I get value of an specific attribute only by XPath?

I have a code like this:
doc = Nokogiri::HTML("<a href='foo.html'>foo</a><a href='bar.html'>bar</a>")
doc.xpath('//a/#href').map(&:value) # => ["foo.html", "bar.html"]
It works as I expected.
But just out of curiosity I want to know, can I also get the value of href attributes only by using XPath?
Locate attributes first
example:
site name:
https://www.easymobilerecharge.com/
We want to locate "MTS" link
In your case, to locate this element, we can use x-path like:
//a[contains(text(),'MTS')]
Now to get href attribute, use:
//a[contains(text(),'MTS')]/#href
Judging from the first answer to this question the answer seems to be yes and no. It offers
xml.xpath("//Placement").attr("messageId")
which is quite close to "only XPath", but not entirely. Up to you to judge if that is enough for you.

Find xml node whose name is a concatenation of attribute of another node and string constant

I have a bit of a tough xpath query (which I'm not entirely sure can be done).
I have the below xml
<Root>
<PersonOne Name='jon'/>
<PersonTwo Name='bob'/>
<JonDetails>some text</JonDetails>
<BobDetails>some details about Bob</BobDetails>
</Root>
I know it is a bit of a contrived example but the xml structure I am dealing with is fixed and I cannot change it.
Basically I'm trying to figure out the xpath to select the *Detail node for the name attribute in the PersonOne node.
So to do this I need to concat the atribute value of 'Name' in the PersonOne node with the constant Details to get 'JonDetails' as a node name.
I have this so far but it doesn't work but I think it is along the right lines.
/Root/*[contains(name(), concat(/Root/PersonOne/#Name, 'Details'))]
However, just to add to the fun it has to be a case insensitive match on the node name. I know this can be done with a translate function.
Any pointers in the right direction?
Jon
will this expression be better?
/Root/*[translate(name(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz') = translate(concat(/Root/PersonOne/#Name, 'details'), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')]
it looks for an exact match.
Just figured it out! It's not too pretty but it works.
/Root/*[contains(translate(name(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), translate(concat(/Root/PersonOne/#Name, 'details'), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'))]
If anyone can improve on this it would be good to see how.
Thanks

Negative decimal value formatting in Altova Style Vision

I have a problem with value formatting in Altova StyleVision. Altova forums seem to be dead. Maybe someone encountered similar problem.
I have created an Auto Calculation inside XBRL table generated by StyleVision. It contains " sum( xbrli:xbrl/n1:Wages ) " xpath expression. This expression gives me a negative value. I want to format it so that it's surrounded by parentheses instead of leading minus.
I have tried using prefixes ans suffixes in "value formatting", like this (###,##0.##) or this [###,##0.##] . But I still get minus instead of parentheses. Is there a way to get around this? Any of those prefixes seem not to work for me at all.
http://manual.altova.com/Stylevision/stylevisionbasic/index.html?svpres_inputformatting.htm
Ok. It seems that problem is solved.
Created ch.xsl file with following contents:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:decimal-format name='ch' grouping-separator=" " decimal-separator=","/>
</xsl:stylesheet>
In Altova StyleVision under Design Overview -> Add new XSLT file. Choose ch.xsl.
Afterwards in Auto Calculation xpath used following expression:
format-number(sum( xbrli:xbrl/n1:Wages ),'### ##0,##;(### ##0,##)','ch')
Maybe there is a better way to do this, but it worked for me. Hope it will help someone

using xpath in selenium.get.Text and selenium.click

I have Адреса магазинов on page and want to store text, then click on this link and verify that the page where am I going to contains this text in headers. So I tried to find element by xpath, and selenium.getText get the right result, but selenium.click goes to another link. Where have I made a mistake? Thanks in advance!
String m_1 = selenium.getText("xpath=html/body/div[3]/div[2]/div[1]/h4[1]");
selenium.click("xpath=html/body/div[3]/div[2]/div[1]/h4[1]");
selenium.waitForPageToLoad("30000");
assertTrue(selenium.getText("css=h3").contains(m_1));
page:http://www.svyaznoy.ru/map/
Resume:
using xpath=//descendant::a[#href='/address_shops/'][2] or css=div.deff_one_column a[href='/address_shops/'] get right results
using xpath=//a[#href='/address_shops/'] - Element is not currently visible
xpath=//a[#href='/address_shops/'][2] - Element not found
There is a missing slash at the beginning of the expression. I am kind of surprised this got through at all - the first slash means "begin at root node".
Also, it is better to select the <a> element instead of the <h>. Sometimes it works, sometimes is misclicks, sometimes the click doesn't do anything at all. Try to be as concrete as you can be.
Try this one.
String m1 = selenium.getText("xpath=/html/body/div[3]/div[2]/div/h4/a");
selenium.click("xpath=/html/body/div[3]/div[2]/div/h4/a");
selenium.waitForPageToLoad("30000");
// your variable is named m1, but m_1 was used here
assertTrue(selenium.getText("css=h3").contains(m1));
By the way, there are even better XPath expressions you could use. See the documentation, it really is helpful. Just an example, this would work, too, and is much easier to write and read:
String m1 = selenium.getText("xpath=//a[#href='/address_shops/']");
selenium.click("xpath=//a[#href='/address_shops/']");
Sorry, didn't notice page link. Css for second link can be something like that css=div.deff_one_column a[href='/address_shops/']

XPath concat multiple nodes

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.

Resources