I want to select String between < and >.
Input :
<p type="Endnote Text"><p:endnote_bl1>This is a bullet list in an endnote</p>
<p type="Endnote Text"><p:endnote_bl2>This is a bullet list in an endnote</p>
<p type="Endnote Text"><p:endnote_bl3>This is a bullet list in an endnote</p>
I want to select p:endnote_bl1,p:endnote_bl2, etc.. from the text. It means whatever text between < and >. How can I write the XPath for this.
In XSLT, using xpath, you can simply select all p elements (or tps:p elements, if you do have namespaces), and use substring-before and substring-after to extract the text, although do note this assumes one occurrence of each of < and >
<xsl:for-each select="//p[#type='Endnote Text']">
<xsl:value-of select="substring-before(substring-after(., '<'), '>')" />
<xsl:text>
</xsl:text>
</xsl:for-each>
See it in action at http://xsltfiddle.liberty-development.net/bnnZX7
If you could use XSLT 2.0, you could do it without the xsl:for-each...
<xsl:value-of select="//p[#type='Endnote Text']/substring-before(substring-after(., '<'), '>')" separator="
" />
Or you could also use replace in XSLT 2.0....
<xsl:value-of select="//p[#type='Endnote Text']/replace(., '<(.+)>.*', '$1')" separator="
" />
You could use just xpath, if we fix your xml like so:
<doc>
<p type="Endnote Text"><p:endnote_bl1>This is a bullet list in an endnote</p>
<p type="Endnote Text"><p:endnote_bl2>This is a bullet list in an endnote</p>
<p type="Endnote Text"><p:endnote_bl3>This is a bullet list in an endnote</p>
</doc>
Then this expression,
doc/p/substring(./text(),2,13)
will select
p:endnote_bl1
p:endnote_bl2
p:endnote_bl3
Related
Hello XPath/Xslt Friends,
i have the following Xml. I want to determine the id of the first matching section or chapter of my cout element. If the the closest node of the cout is a chapter, then i will get the chapter id, otherwise the section id.
<book>
<chapter id="chapter1">
<aa>
<cout></cout> --> i will get "chapter1"
</aa>
<section id="section1">
<a>
<b>
<cout></cout> --> i will get section1
</b>
</a>
</section>
<section id="section2">
<a>
<b>
<cout></cout> --> i will get section2
</b>
</a>
</section>
</chapter>
</book>
i tried the following statement:
<xsl:value-of select="ancestor::*[local-name() = 'section' or local-name() = 'chapter']/#id" />
but in case of the cout contained in section1, it will give me chapter1, instead of section1. Any solutions?
Your current statement is selecting all ancestors with the name section or chapter, and after being selected, xsl:value-of will only return the value of the first one, in document order (in XSLT 1.0 that is).
Try this instead
<xsl:value-of select="ancestor::*[local-name() = 'section' or local-name() = 'chapter'][1]/#id" />
if cout has no ancestor section , print chapter id
else print section id.
<xsl:for-each select="//cout">
<xsl:if test="count(ancestor::section)= 0">
<xsl:value-of select="ancestor::chapter/#id"/>
</xsl:if>
<xsl:if test="count(ancestor::section)>0">
<xsl:value-of select="ancestor::section/#id"/>
</xsl:if>
</xsl:for-each>
My XML code
<INSTRUCTION_LIST>
<INSTRUCTION_LIST_ITEM>
<NTC_NAV3INSTRUCT>
<IMMUTABLE_ID>5790</IMMUTABLE_ID>
<DESCRIPTION>
<P>Buongiorno</P>
<P>come</P>
<P>andiamo</P>
<P>stasera</P>
<P>?</P>
</DESCRIPTION>
</NTC_NAV3INSTRUCT>
</INSTRUCTION_LIST_ITEM>
<INSTRUCTION_LIST_ITEM>
<NTC_NAV3INSTRUCT>
<IMMUTABLE_ID>5791</IMMUTABLE_ID>
<DESCRIPTION>QUESTA MACCHINA E BELLISSIMA</DESCRIPTION>
</NTC_NAV3INSTRUCT>
</INSTRUCTION_LIST_ITEM>
</INSTRUCTION_LIST>
The XSLT:
<xsl:for-each select="following-sibling::INSTRUCTION_LIST//DESCRIPTION">
<div>
<xsl:value-of select="."/>
</div>
</xsl:for-each>
I obtain this result
Buongiorno come andiamo stasera?
QUESTA MACCHINA E BELLISSIMA
IS not correct i would this result:
Buongiorno
come
andiamo
stasera
?
QUESTA MACCHINA E BElLISSIMA
I would that result respect <P> tag.
Value-of gets you string value of selected node (i.e. concatenated strings of this nodes and its descendants). Try to use copy-of instead.
Source:
<txt>
<Data>
<div class="label">
<span>Welcome</span>
<span id="UserName"></span>.
</div>
</Data>
</txt>
Output required:
<Data>
<div class="label">
<span>Welcome</span>
<span id="UserName"></span>.
</div>
</Data>
Rule:
I want to replace
< with <
> with >
There are other characters also, for simplicity I have mentioned two only.
I am not sure how to search for a string in xslt and replace it.
You could achieve this by using disable-output-escaping
<xsl:template match="txt">
<xsl:value-of select="." disable-output-escaping="yes" />
</xsl:template>
That should give you the output you require.
I have an XML like
<emps>
<emp id='3432'>
<fname>Jack</fname>
<lname>Dawson</lname>
<emp>
<emp id='1122'>
<fname>Jack</fname>
<lname>Thompson</lname>
<emp>
<emps>
I am developing a web application which searches this xml based on the first name entered and comes up with a resultant page. To achieve this I have written an xslt to transform the XML to HTML based on the input search string which is passed as a variable named srchStr.
<xsl:template match="employees">
<xsl:for-each select="emp[fname=$srchStr]">
<tr>
<xsl:variable name="id">
<xsl:value-of select="#id" />
</xsl:variable>
<td>
<a href='detailSearch.do?id={$id}'>
<xsl:value-of select="fname" />
,
<xsl:value-of select="lname" />
</a>
</td>
</tr>
</xsl:for-each
</xsl:template>
But the user may enter the name either in upper case or lower case. So how to convert the first name inside the xml tag fname to lower case and do the comparison?
Can some one put a code snippet to use fn:lower-case inside my xsl.
To convert a string to lower case or uppercase you can use the XPath 1.0 function translate:
First define your alphabets for lower case and upper case letters. Note that the position of each pair of characters needs to be the same:
<xsl:variable name="lcletters">abcdefghijklmnopqrstuvwxyz</xsl:variable>
<xsl:variable name="ucletters">ABCDEFGHIJKLMNOPQRSTUVWXYZ</xsl:variable>
Then you can convert to upper case:
<xsl:value-of select="translate($toconvert,$lcletters,$ucletters)"/>
or to lower case
<xsl:value-of select="translate($toconvert,$ucletters,$lcletters)"/>
emp[lower-case(fname)=lower-case($srchStr)]
Or, if you have XPath 1.0 only, you may try using translate like here:
http://geekswithblogs.net/TimH/archive/2006/07/06/84229.aspx
Be warned though, the example with translate would not work on names with accents (like mine :)
I have the following xsl template:
<xsl:template match="para">
<fo:block xsl:use-attribute-sets="paragraph.para">
<!-- if first para in document -->
<!--<xsl:if test="//para[1] intersect .">-->
<xsl:if test="//para[1] intersect .">
<xsl:attribute name="space-after">10pt</xsl:attribute>
<xsl:attribute name="background-color">yellow</xsl:attribute>
</xsl:if>
<xsl:choose>
<xsl:when test="preceding-sibling::*[1][self::title]">
<xsl:attribute name="text-indent">0em</xsl:attribute>
</xsl:when>
<xsl:when test="parent::item">
<xsl:attribute name="text-indent">0em</xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="text-indent">1em</xsl:attribute>
</xsl:otherwise>
</xsl:choose>
<xsl:apply-templates/>
</fo:block>
</xsl:template>
The problem I am having is verifying that the current node of the template is the very first para node in the document from the following xml:
<document>
<section>
<paragraph>
<para>Para Text 1*#</para>
<para>Para Text 2</para>
</paragraph>
</section>
<paragraph>
<para>Para Text 3*</para>
<para>Para Text 4</para>
<para>Para Text 5</para>
<sub-paragraph>
<para>Para Text 6*</para>
<para>Para Text 7</para>
</sub-paragraph>
</paragraph>
<appendix>
<paragraph>
<para>Para Text 8*</para>
</paragraph>
<paragraph>
<para>Para Text 9</para>
</paragraph>
</appendix>
</document>
the xpath I am currently using is "//para[1] intersect ." which is selecting the first para for each group of para (denoted with a * in XML sample). Any ideas on how I can just select the first occurance of para within document (denoted with a #)?
In XPath 1.0 (XSLT 1.0) one can use:
count( (//para)[1] | .) = 1
This works also in XPath 2.0, but may not be as efficient as using the intersect operator.
I would recommend the following XPath 2.0 expression:
(//para)[1] is .
Do note the use of the XPath 2.0 is operator.
I have worked out the solution myself, a slight change is needed in the xpath adding brackets around the //para limits the selection:
"(//para)[1] intersect ." you can also use "(//para)[1] is ." to get the same result, and on this occassion I belive the "is" version is more readable.