I have the following XML structure:
<itemsWithLabels>
<itemLabelValue>
<label>A</label>
<value>a</value>
</itemLabelValue>
<itemLabelValue>
<label>B</label>
<value>b</value>
</itemLabelValue>
<itemLabelValue>
<label>C</label>
<value>c</value>
</itemLabelValue>
</itemsWithLabels>
Using XSL I want to be able to get the value from <value> by knowing the label in <label>.
So my transformation looks like this:
<xsl:value-of select="$content/itemsWithLabels/itemLabelValue/value[#label='A']" />
But clearly something is wrong because I don't have any output.
What am I doing wrong?
Try:
<xsl:value-of select="$content/itemsWithLabels/itemLabelValue[label='A']/value" />
$content/itemsWithLabels/itemLabelValue[label='A'] gets itemLabelValue elements with a label element child having value A. The /value part gets the child value element.
Related
I am new to XSL.I have an XML as below, If CoverageCode equals -'HomeCoverage' then I have to verify for the next 3 elements of 'roofRestrictionEndt','sidingRestrictionEndt'and 'paintRestrictionEndt' . If 'roofRestrictionEndt' exits and its value is 'Y' then I need to print 'Roof' under the 'results' tag, If 'sidingRestrictionEndt' exists and its value is 'Y' then I need to print 'siding' in case if it exists along with the above one then I need to print 'Roof; siding'. If 'paintRestrictionEndt' exists and its value is 'Y' along with the other 2 elements then I need to print 'Roof; siding; paint'. I tried by declaring variables and wrote If conditions and tried to append values accordingly inside IF condition, but I came to know the declared variables are immutable. In java, we can achieve this by using StringBuffer. Is there any way to achieve this in XSL? Below is XML.
<locationCoverage ID="3">
<coverageCode >HomeCoverage</coverageCode>
<roofRestrictionEndt >Y</roofRestrictionEndt>
<sidingRestrictionEndt>Y</sidingRestrictionEndt>
<paintRestrictionEndt >Y</paintRestrictionEndt>
<locationCoverage>
Results should look like as below
<results>
<result>Roof;siding;paint</result>
</results>
If I have below input XML
<locationCoverage ID="3">
<coverageCode >HomeCoverage</coverageCode>
<roofRestrictionEndt >Y</roofRestrictionEndt>
<paintRestrictionEndt >Y</paintRestrictionEndt>
</locationCoverage>
For the above XML results should look like as below
<results>
<result>Roof;paint</result>
</results>
Appreciate it If anyone helps me with this. Thanks in advance.
If I understand this correctly (which is not at all certain), you want to do something like:
<xsl:template match="locationCoverage[coverageCode='HomeCoverage']">
<xsl:variable name="test-results">
<xsl:if test="roofRestrictionEndt='Y'">Roof </xsl:if>
<xsl:if test="sidingRestrictionEndt='Y'">siding </xsl:if>
<xsl:if test="paintRestrictionEndt='Y'">paint</xsl:if>
</xsl:variable>
<result>
<xsl:value-of select="translate(normalize-space($test-results), ' ', ';')"/>
</result>
</xsl:template>
XLST receiving the date from apache-camel in below formate.
data format
<list>
<linked-hash-map>
<entry key="NAME">test1</entry>
</linked-hash-map>
<linked-hash-map>
<entry key="NAME">test2</entry>
</linked-hash-map>
</list>
My XSLT:
<xsl:stylesheet>
<xsl:template match="*">
<xsl:for-each select="//*[local-name()='linked-hash-map']">
<tag1>
<xsl:value-of select="string(//*[local-name()='entry'][#key='NAME'])"/>
</tag1t>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
OUTPUT always returns the first element.
<tag1>test1<tag1>
<tag1>test1<tag1>
What is wrong in above xslt and help generate xml with all elements.
Because path expressions starting with "//" select from the root of the document tree, you are selecting the same nodes every time in your xsl:value-of; and in XSLT 1.0, if you select multiple nodes, only the first one gets displayed.
Methinks you're using "//" because you've seen it in example code and don't actually understand what it means...
Within xsl:for-each, you normally want a relative path that selects from the node currently being processed by the for-each.
You've also probably picked up this *[local-name()='linked-hash-map'] habit from other people's code. With no namespaces involved, you can safely replace it with linked-hash-map.
xsl
<xsl:variable name="varName>
<xsl:value-of select="/can/be/a/long/path/down/xml/item[#id=1] />
</xsl:variable>
xml
<xml>
<item id="1" text="Yes">
<item id="2" text="No">
</xml>
use
I was thinking I could use like this:
<xsl:when test="$varName/#text = 'Yes'">
blah
</xsl:when>
but blank space is generated in place of variable. Is this even possible, have a node as a variable and use elsewhere?
<xsl:variable name="varName">
<xsl:value-of select="/can/be/a/long/path/down/xml/item[#id=1]" />
</xsl:variable>
This is one of the most common XSLT errors I see. Usually what people intended is:
<xsl:variable name="varName" select="/can/be/a/long/path/down/xml/item[#id=1]"/>
And most of the time, the code works just fine, except that it's a lot slower than it needs to be. But sometimes the fact that the two constructs are quite different beneath the covers comes back to bite you.
To understand the difference, xsl:variable with a select attribute binds the variable to whatever the select expression evaluates to, which in this case is a set of zero or more item elements. By contrast, xsl:variable with nested instructions creates a document node (XSLT 2.0) or result tree fragment (XSLT 1.0) whose content is a COPY of whatever those instructions produce. In this case, because the content is an xsl:value-of instruction, the variable contains a copy of the string-value of the selected node.
And of course, the string value of the selected node doesn't have any attributes, so test="$varname/#text = 'x'" will always return false.
I want to get the value of a specific node, specified by its id attribute. But the behaviour of my XSL parser, Saxon, is not how I expected it to work.
This is my XSL code:
<xsl:template match="synonyme">
<xsl:element name="corr">
<xsl:value-of select="#connecteur" />
<xsl:value-of select="/liste/connecteur[#id=#connecteur]/forme[1]" />
</xsl:element>
</xsl:template>
I just matched a tag named synonyme which has a connecteur attribute. My code outputs the value of this attribute.
I also want to output the value of another node which has an id attribute matching the connecteur attribute of my currently matched synonyme tag. But no results are ever found for this query, the second value-of always has empty output.
If I write, e.g. [#id='c160'], where c160 is the exact same thing that is output by the first value-of, it works! But not when comparing to the #attribute of my matched node. How can I fix this?
The XML is basically
<liste><connecteur id="c160"><forme>foo</forme></connecteur>
<connecteur id="c161"><synonyme connecteur="c160" /></connecteur>
</liste>
and the expected output in place of the synonyme is <corr>c160 foo</corr>.
The predicate you use:
[#id=#connecteur]
is looking for an element with two attributes - id and connecteur- with equal values. To look for an element with an id attribute whose value matches the value of the current element's connecteur value, you need to use:
[#id=current()/#connecteur]
See: https://www.w3.org/TR/xslt/#function-current
A better solution would be to define a key as:
<xsl:key name="ref" match="connecteur" use="#id" />
then use:
<xsl:value-of select="key('ref', #connecteur)/forme" />
to resolve the cross-reference.
See: https://www.w3.org/TR/xslt/#key
I am new to this forum. I need to parse/read an xml which cotains lots of metadata(as below). I have two read a specific meta value based on the bu value, for example if my bu value is '987654321abcdefghijklmnopaslasjdoiwneois123abc' I have to get the value "d581452fa9ba3110VgnVCM10000038ccc5abRCRD|def". My question, is there any restriction with metadata name length? for some reason my xslt logic is not reading this value(select="MT[#N=$partialval]/#V").
XSLT snippet:
<xsl:for-each select='./MT[#N="bu"]'>
<xsl:variable name="temp_bu" select="./#V"/>
<xsl:variable name="partialval" select="'987654321abcdefghijklmnopaslasjdoiwneois123abc'"/>
<xsl:if test="contains($partialval, $temp_bu)">
<xsl:variable name="partialbuval" select="MT[#N=$partialval]/#V"/>
<xsl:value-of disable-output-escaping='yes' select="concat('file://',$partialbuval,'test',$partialval)"/>
</xsl:if>
</xsl:for-each>
Sample xml structure:
<MT N="bu" V="12345678910111121314sdnfske34234123234abc"/>
<MT N="12345678910111121314sdnfske34234123234abc" V="02715148a3e7a110VgnVCM1000001b89c5abRCRD|abc"/>
<MT N="12345678910111121314sdnfske34234123234abc_name" V="Item one"/>
<MT N="bu" V="987654321abcdefghijklmnopaslasjdoiwneois123abc"/>
<MT N="987654321abcdefghijklmnopaslasjdoiwneois123abc" V="d581452fa9ba3110VgnVCM10000038ccc5abRCRD|def"/>
<MT N="987654321abcdefghijklmnopaslasjdoiwneois123abc_name" V="Item two"/>
<MT N="bu" V="qqqqqwwwweeeee1112223333ssdfff3334sssssabc"/>
<MT N="qqqqqwwwweeeee1112223333ssdfff3334sssssabc" V="d581452fa9ba3110VgnVCM10000038ccc5abRCRD|ghi"/>
<MT N="qqqqqwwwweeeee1112223333ssdfff3334sssssabc_name" V="Item three"/>
<MT N="bu" V="hhhheeeertisodfnsdifwoein12345sfjsoif234defgh"/>
<MT N="hhhheeeertisodfnsdifwoein12345sfjsoif234defgh" V="d581452fa9ba3110VgnVCM10000038ccc5abRCRD|jkl"/>
<MT N="hhhheeeertisodfnsdifwoein12345sfjsoif234defgh_name" V="Item four"/>
Seeing the output as (partialbuval value is missing in this string)
"file://test987654321abcdefghijklmnopaslasjdoiwneois123abc"
I am not sure what mistake I am doing here. Appreciate if you could help me.
Thanks,
Amarnath
I am not sure I understand your requirement. But in the following:
<xsl:for-each select="./MT[#N="bu"]">
<xsl:variable ... select="MT[#N=$partialval]/#V"/>
</xsl:for-each>
the second select will never select anything. That is because xsl:for-each changes the context. So within the body of the xsl:for-each (also called its sequence constructor) the context item is the current MT element being looked at in this current iteration of the xsl:for-each.
So the second select expression asks for any MT element, direct child of the current MT element, and there is not any.
Extra tip: ./ at the beginning of an XPath expression is always meaningless. The only situation where starting an expression with a dot is .//. So ./MT is always equivalent to MT, which is also more readable.