Xpath Matching a node and getting the value of it - xslt

Below is the xml file:
file1.xml
<?xml version="1.0" encoding="UTF-8"?><W4N xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:functx="http://www.functx.com"><LUNGROUP><OBJECT lungroupID="0" lunIds="0,221,228"/></LUNGROUP><LUNGROUP><OBJECT lungroupID="1" lunIds="1,3,5/></LUNGROUP></W4N>
I want to match on lunIds. I have given the below xpath expression /W4N/LUNGROUP/OBJECT[tokenize(#lunIds,',')='228']
Its showing the result as Elements found: 1
Now my requirement is to get the lungroupID of the matched element.How can I do this using xpath? Any help is highly appreciated.

I don't see the XML you intended to post, but you should be able to add the attribute you want at the end of your xpath expression:
/W4N/LUNGROUP/OBJECT[tokenize(#lunIds,',')='228']/#lungroupID

Related

how to use '*' in XPATH starts-with()?

we received banking statements from the SAP System. We sometimes observe the naming convention of the file name will be not as per the standards and the files will be rejected.
We wanted to validate the file name, as per the below example, we get the file name in the name attribute.
Can the country ISO code escape in the validation?
We wanted an Xpath that captures GLO_***_UPLOAD_STATEMENT like this so that ISO code is not validated.
Example XML:
<?xml version="1.0" encoding="UTF-8"?>
<Details name="GLO_ZFA_UPLOAD_STATEMENT" type="banking" version="3.0">
<description/>
<object>
<encrypted data="b528f05b96102f5d99743ff6122bb0984aa16a02893984a9e427a44fcedae1612104a7df1173d9c61a99ebe0c34ea67a46aecc86f41f5924f74dd525"/>
</object>
</Details>
Xpath tried:
Details[#type="banking"]/#name[not(starts-with(., "GLO_***_UPLOAD_STATEMENT"))]
which is not working :(
Can anyone help here, please :)
Thanks in advance!
Try using the matches() function for a regex like this:
Details[#type="banking"]/#name[not(matches(., "^GLO_(.){3}_UPLOAD_STATEMENT"))]
starts-with() is char based, it doesn't recognize patterns.
If your XPath version doesn't support regex then you can use something like:
Details[#type="banking"]/#name[not(starts-with(., "GLO_")) and not(ends-with(., "_UPLOAD_STATEMENT"))]
You can match regular expressions using the matches() function. For example:
//Details[#type="banking" and not(matches(#name, "GLO_[A-Z]*_UPLOAD_STATEMENT"))]/#name
Will only select Details node's name attribute for Details that have type="banking" and name not matching the regular expression "GLO_[A-Z]*_UPLOAD_STATEMENT". You can refine the regex as needed.

Get XSLT result as text and use in another XSLT

I have a requirement to use one XSLT result as text value for an element in another XSLT.
Example: My output XML should be like
<?xml version="1.0" encoding="utf-8"?>
<root>
<a>xxx</a>
<b>yyy</b>
<c>
<?xml version="1.0" encoding="utf-8"?><order><header>....</order>
</c>
</root>
"Order.xsl" is used to get XML.
"Main.xsl" is used to get XML which has to call "Order.xsl" and get the result as text for element.
Please can you give your suggestions?
Thanks
Your output "XML" is not actually well-formed XML so you can't produce it using XSLT. It wouldn't be very useful if you could, because no XML parser would accept it. An XML declaration is permitted only at the start of the XML document.

How to avoid Open xml tag on its own line

I have an XML structure as below:
<?xml version="1.0" encoding="utf-8"?>
<cl:doc identifier="ISBN" xsi:schemaLocation="http://xml.cengage-learning.com/cendoc-core cendoc.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cl="http://xml.cengage-learning.com/cendoc-core" xmlns:m="http://www.w3.org/1998/Math/MathML">
<cl:chapter identifier="ch01">
<cl:opener identifier="ch06_opn">
<cl:introduction identifier="ch06_int">
<cl:list identifier="tu_1" list-style="Unformatted" item-length="long">
<cl:item identifier="tu_2"><cl:para identifier="ch01_dum_2">Solubility</cl:para></cl:item>
<cl:item identifier="tu_3"><cl:para identifier="ch01_dum_3">Polarity</cl:para></cl:item>
</cl:list></cl:introduction></cl:opener></cl:chapter></cl:doc>
When I transform this above xml using XSLT, I got the below output:
<?xml version="1.0" encoding="utf-8"?>
<cl:doc identifier="ISBN" xsi:schemaLocation="http://xml.cengage-learning.com/cendoc-core cendoc.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cl="http://xml.cengage-learning.com/cendoc-core" xmlns:m="http://www.w3.org/1998/Math/MathML"><cl:chapter identifier="ch01">
<cl:opener identifier="ch06_opn">
<cl:introduction identifier="ch06_int"><cl:list identifier="tu_1" list-style="Unformatted" item-length="long">
<cl:item identifier="tu_2"><cl:para identifier="ch01_dum_2">Solubility</cl:para></cl:item>
<cl:item identifier="tu_3"><cl:para identifier="ch01_dum_3">Polarity</cl:para></cl:item></cl:list></cl:introduction></cl:opener></cl:chapter></cl:doc>
Here, the opening tag <cl:opener identifier="ch06_opn"> alone comes on separate line. This result me to have the blank line after doing the conversion.
I need this <cl:opener identifier="ch06_opn"> tag must be run-on with either its previous line or to the next line.
Can anybody help me how this can be achieved through XSLT.
Thanks,
Gopal
Without seeing your XSLT it's difficult to be certain, but it sounds like your XSLT is copying over the whitespace in the source into the output.
The quickest way to prevent that is to put
<xsl:strip-space elements="*"/>
or alternatively
<xsl:template match="text()[not(normalize-space())]"/>
This removes all whitespace, but you can of course be more specific about the whitespace you're removing, such as
<xsl:template match="cl:opener/text()[1][not(normalize-space())]"/>
to remove just the whitespace after that opening element tag- this matches the first text node within cl:opener if it's whitespace only, and outputs nothing in it's place.

confusing statement while version change

I've the below XSLT statement.
<xsl:value-of select="substring-after(
./title/content-style/text(),' ')" />
when i use the style sheet version 1 as
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ntw="Number2Word.uri"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="ntw">
But when i change it to version 2.0 as below.
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ntw="Number2Word.uri"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="ntw">
it is throwing the below error
XSLT 2.0 Debugging Error: Error:
file:///C:/Users/u0138039/Desktop/Proview/HK/HKWB2014/XSLT%20and%20CSS/new_bull.xsl:202:
Wrong occurrence to match required sequence type -
Details: - XPTY0004: The supplied sequence ('2' item(s)) has
the wrong occurrence to match the sequence type xs:string ('zero or
one')
please let me know what is going right in XSL1.0 is going wrong in XSL 2.0.
Thanks
In XSLT 1.0, when you pass a node set of more than one node to a function that expects a single string, it simply uses the string value of the first node in the set and ignores the rest of them. In XSLT 2.0 the substring-after function expects its arguments to be xs:string?, i.e. zero or one string, so if you pass it a sequence with more than one item it will cause a type mismatch error.
I presume that ./title/content-style/text() selects more than one node, i.e. there's more than one title, more than one content-style and/or more than one text node within the content-style element.
Consider whether you actually need to use text() here at all - do you really need to process each text node child of content-style individually, or do you just want the string value of the content-style element as a whole? If the former, you need something like title/content-style/text()/substring-before(., ' ') (which only works in 2.0), if the latter, try just saying substring-after(title/content-style, ' ').
I had the same issue, but for me, it turned out that while my schema, for the element in question, had the multiplicity optional setting, it did not have the unbounded setting, and the input data I was using had 2 elements where it was expecting 0...1

XSLT whitespace elements getting trimmed

Quick question. I have some XML
<someXML>
<someNode> </someNode>
<someNode>asdlkjf </someNode>
</someXML>
When i apply an XSLT to this the first node is getting trimmed into nothing. The second is fine and the trailing whitespace is not trimmed because i'm preserving whitespace:
<someXML>
<someNode></someNode>
<someNode>asdlkjf </someNode>
</someXML>
My question is why is the first node getting truncated? As absurd as this sounds, the whitespace node is important and needs to be maintained. I'm using Xalan 2.7.1. Is this just the way XSL works or is there a way around this?
Thanks!
Use this XSLT directive:
<xsl:preserve-space elements="*"/>
If this doesn't help, this means that the XML parser is stripping the whitespace-only text nodes.
To prevent this, in the XML document use the xml:space="preserve" attribute:
<someXML>
<someNode xml:space="preserve"> </someNode>
<someNode>asdlkjf </someNode>
</someXML>