I am not certain why my xslt won't put a new line in my output...
This is my xslt....
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
<xsl:output method="text" encoding="iso-8859-1"/>
<xsl:variable name="newline"></xsl:variable>
<xsl:template name="FairWarningTransform" match="/"> <!--#* | node()">-->
<xsl:for-each select="//SelectFairWarningInformationResult">
<xsl:value-of select="ApplicationID"/>,<xsl:value-of select="USERID"/>
</xsl:for-each>
* Note. This report outlines Fair warning entries into reported for the above time frame.
</xsl:template>
</xsl:stylesheet>
Here is my output...
1,TEST1,test2,
I want it to look like...
1,TEST
1,test2,
Why isn't this character
creating a newline
Try replacing
with
<xsl:text>
</xsl:text>
That helps XSLT distinguish it from other whitespace in your stylesheet that is part of the stylesheet formatting (not part of the desired output).
XSLT's default behavior is to ignore any text nodes in the stylesheet that are entirely whitespace (this is true even if some of the whitespace is encoded as entities like
), except for text inside <xsl:text>, which is preserved.
I suggest replacing these lines:
<xsl:value-of select="ApplicationID"/>,<xsl:value-of select="USERID"/>
with this:
<xsl:value-of select="concat(ApplicationID, ',', USERID, '
')"/>
That way the newline should be ensured to be included in the output.
Try using this as your newline instead of the escaped character:
<xsl:text>
</xsl:text>
Related
I have following code
<xsl:value-of select=concat(substring(DBColumn, string-length(DBColumn)-3),concat('-',DBColumn))
It results me
230-Virginia-230.
I want it as 230-Virginia.
Originally in database it is as Virginia-230
Furthermore
ABC, 230-Virginia
How to trim whitespace in the same mentioned code so that it should look like as follow ABC,230-Virginia
It's not clear what exactly your question is.
To answer the question as stated in your title: you can remove the last N characters from a string using:
substring($string, 1, string-length($string) - $N)
Trying to illustrate with an input document that contains the data that you mentioned:
<input>
<DBColumn>Virginia-230</DBColumn>
<other>ABC </other> <!-- N.B. trailing space -->
</input>
This XSLT 3.0 stylesheet does some of the things that you mentioned in the "proposed value". I've also included the input value and the "old-value" with the value-of expression that you mentioned in your post.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0"
exclude-result-prefixes="#all">
<xsl:output method="xml" indent="yes" />
<xsl:template match="/input">
<output>
<input-value><xsl:value-of select="DBColumn" /></input-value>
<old-output-value>
<xsl:value-of
select="concat(substring(DBColumn, string-length(DBColumn)-3),
concat('-', DBColumn))"/>
</old-output-value>
<proposed-value>
<xsl:value-of
select="normalize-space(other)
|| ',' ||
string-join(reverse(tokenize(DBColumn, '-')), '-')"
/>
</proposed-value>
</output>
</xsl:template>
</xsl:stylesheet>
which produces:
<output>
<input-value>Virginia-230</input-value>
<old-output-value>-230-Virginia-230</old-output-value>
<proposed-value>ABC,230-Virginia</proposed-value>
</output>
For an xsl:value-of() that I believe works in XSLT1.0 (but I won't guarantee), you could try:
<xsl:value-of
select="concat(other, ',',
substring-after(DBColumn, '-'),
'-',
substring-before(DBColumn, '-'))" />
which does not address the trailing space in other but at least suggests how to reverse the two values around the '-' char in DBColumn.
For suggestions on removing leading/trailing spaces on string, see: XSLT 1.0 to remove leading and trailing spaces
I'm using XSLT to extract some data from a trademark XML file from the Patent and Trademark Office. It's mostly okay, except for one blank line. I can get rid of it with a moderately ugly workaround, but I'd like to know if there a better way.
Here's a subset of my XSLT:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:tm="http://www.wipo.int/standards/XMLSchema/trademarks" xmlns:pto="urn:us:gov:doc:uspto:trademark:status">
<xsl:output method="text" encoding="utf-8" />
<xsl:strip-space elements="*"/>
<xsl:template match="tm:Transaction">
<xsl:apply-templates select=".//tm:TradeMark"/>
<xsl:apply-templates select=".//tm:ApplicantDetails"/>
<xsl:apply-templates select=".//tm:MarkEvent"/>
</xsl:template>
<xsl:template match="tm:TradeMark">
MarkCurrentStatusDate,"<xsl:value-of select="normalize-space(tm:MarkCurrentStatusDate)"/>"<xsl:text/>
ApplicationNumber,"<xsl:value-of select="normalize-space(tm:ApplicationNumber)"/>"<xsl:text/>
ApplicationDate,"<xsl:value-of select="normalize-space(tm:ApplicationDate)"/>"<xsl:text/>
RegistrationNumber,"<xsl:value-of select="normalize-space(tm:RegistrationNumber)"/>"<xsl:text/>
RegistrationDate,"<xsl:value-of select="normalize-space(tm:RegistrationDate)"/>"<xsl:text/>
<xsl:apply-templates select="tm:WordMarkSpecification"/>
<xsl:apply-templates select="tm:TradeMarkExt"/>
<xsl:apply-templates select="tm:PublicationDetails"/>
<xsl:apply-templates select="tm:RepresentativeDetails"/>
</xsl:template>
<xsl:template match="tm:WordMarkSpecification">
MarkVerbalElementText,"<xsl:value-of select="normalize-space(tm:MarkVerbalElementText)"/>"<xsl:text/>
</xsl:template>
It has a few more templates, but that's the gist of it. I always get a blank line at the very beginning of the output, before any data; I don't get any other blank lines. My circumvention is to combine the two lines:
<xsl:template match="tm:TradeMark">
MarkCurrentStatusDate,"<xsl:value-of select="normalize-space(tm:MarkCurrentStatusDate)"/>"<xsl:text/>
into a single line:
<xsl:template match="tm:TradeMark">MarkCurrentStatusDate,"<xsl:value-of select="normalize-space(tm:MarkCurrentStatusDate)"/>"<xsl:text/>
This works, and I guess I'm okay with it if there's nothing better, but it seems inelegant and like a kludge to me. None of the other templates need this treatment (e.g. the tm:WordMarkSpecification template or another six after that)), and I'm confused why it's needed here. Any ideas?
Because I can see the specific point in the XSLT that's inserting the blank line, I presume it's not helpful to provide the XML I'm testing on, but if you do need to see it, you can get it at https://tsdrapi.uspto.gov/ts/cd/casestatus/rn2178784/download.zip ; it's the XML file in that archive.
Use at the beginning of the template the same trick you are using at the end of the template to chop up the stylesheet node tree with empty <xsl:text/> instructions:
<xsl:template match="tm:TradeMark">
<xsl:text/>MarkCurrentStatusDate,"<xsl:value-of select="normalize-space(tm:MarkCurrentStatusDate)"/>"<xsl:text/>
Personally, I think it's cleaner to use a concat() when you need to combine static text and dynamic values:
<xsl:template match="tm:TradeMark">
<xsl:value-of
select="concat(
'MarkCurrentStatusDate,"', normalize-space(tm:MarkCurrentStatusDate), '"',
'ApplicationNumber,"', normalize-space(tm:ApplicationNumber), '"',
'ApplicationDate,"', normalize-space(tm:ApplicationDate), '"',
'RegistrationNumber,"', normalize-space(tm:RegistrationNumber), '"',
'RegistrationDate,"', normalize-space(tm:RegistrationDate), '"'
)"/>
<xsl:apply-templates select="tm:WordMarkSpecification"/>
<xsl:apply-templates select="tm:TradeMarkExt"/>
<xsl:apply-templates select="tm:PublicationDetails"/>
<xsl:apply-templates select="tm:RepresentativeDetails"/>
</xsl:template>
This should also solve your issue with the blank spaces showing up.
Remember you can always just play with the XML syntax to ignore end-of-line sequences that are inside of start and end tag delimiters:
<xsl:template match="tm:TradeMark"
>MarkCurrentStatusDate,"<xsl:value-of select="normalize-space(tm:MarkCurrentStatusDate)"
/>"ApplicationNumber,"<xsl:value-of select="normalize-space(tm:ApplicationNumber)"
/>"ApplicationDate,"<xsl:value-of select="normalize-space(tm:ApplicationDate)"
/>"RegistrationNumber,"<xsl:value-of select="normalize-space(tm:RegistrationNumber)"
/>"RegistrationDate,"<xsl:value-of select="normalize-space(tm:RegistrationDate)"
/>"<xsl:apply-templates select="tm:WordMarkSpecification"/>
<xsl:apply-templates select="tm:TradeMarkExt"/>
<xsl:apply-templates select="tm:PublicationDetails"/>
<xsl:apply-templates select="tm:RepresentativeDetails"/>
</xsl:template>
There is no rule in XML that a tag's closing delimiter /> has to be on the same line as the tag's opening delimiter <. White-space inside of a tag is ignored (where innocuous), and an end-of-line sequence is considered white-space.
If you want all of the text to be emitted without extra line breaks or white-space, then put the literal text inside of <xsl:text> elements.
<xsl:template match="tm:TradeMark">
<xsl:text>MarkCurrentStatusDate,"</xsl:text>
<xsl:value-of select="normalize-space(tm:MarkCurrentStatusDate)"/>
<xsl:text>"</xsl:text>
<xsl:text>ApplicationNumber,"</xsl:text>
<xsl:value-of select="normalize-space(tm:ApplicationNumber)"/>
<xsl:text>"</xsl:text>
<xsl:text>ApplicationDate,"</xsl:text>
<xsl:value-of select="normalize-space(tm:ApplicationDate)"/>
<xsl:text>"</xsl:text>
<xsl:text>RegistrationNumber,"</xsl:text>
<xsl:value-of select="normalize-space(tm:RegistrationNumber)"/>
<xsl:text>"</xsl:text>
<xsl:text>RegistrationDate,"</xsl:text>
<xsl:value-of select="normalize-space(tm:RegistrationDate)"/>
<xsl:text>"</xsl:text>
<xsl:apply-templates select="tm:WordMarkSpecification"/>
<xsl:apply-templates select="tm:TradeMarkExt"/>
<xsl:apply-templates select="tm:PublicationDetails"/>
<xsl:apply-templates select="tm:RepresentativeDetails"/>
</xsl:template>
That way, none of the line breaks and white-space inside of the <xsl:template> will be seen as significant and will not be included in the result tree output.
I have a input XML like this :
<in_xml>
<company>
<project>
ProjNo1
ProjNo2
ProjNo3
</project>
</company>
</in_xml>
A simple XSLT is applied to this source, which writes another XML with the value of Project Tag.
The Project tag in input xml has three lines , it could be one or more line(s). I am looking at way for the XSLT to read only the first line, in case there are more than one and write the first line in the output xml.
The current XSLT is very simple as it just reads the Project tag and spits out the value, hence the code is not attached.
Regards.
I have added the answer to the question, see below #Maestro's answer.
If you are in the happy circumstances of being able to apply XSLT 2.0, the following may help:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="//project/text()">
<xsl:value-of select="tokenize(normalize-space(.),' ')[1]" />
</xsl:template>
</xsl:stylesheet>
Explanation: first normalize-space() to replace all whitespace strings by a single blank (and cut off leading and trailing whitespace), then split into words, then take the first one.
In XSLT 1.0 you could use
<xsl:value-of select="substring-before(normalize-space(.), ' ')"/>
instead. Less flexible if the second word has to be selected, but for the first word it works OK.
EDIT
you asked how to retrieve a first line in XSLT 1.0 - problem here is the leading whitespace which may contain a LF so you cannot just substring-before the first LF.
The below can probably be improved upon, but it works fine:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="//project/text()">
<xsl:variable name="afterLeadingWS"
select="substring-after(., substring-before(.,substring-before(normalize-space(.), ' ')))"/>
<xsl:choose>
<xsl:when test="contains($afterLeadingWS, '
')">
<xsl:value-of select="substring-before($afterLeadingWS, '
')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$afterLeadingWS"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
Explanation: first get first word as before, then determine the whitespace before that first word, then get everything after that leading whitespace, then get the first line, which is the string before a LF character. It may just happen that there is no LF except maybe in the leading whitespace, hence the choose function.
first up thanks to #Maestro for taking time out and helping me, appreciate your help.
Here is the code that I used to get the first line from a paragraph of text that has a CR:
<xsl:variable name="projNumber" select="ProjectNumber" />
<xsl:variable name="crlf" select="'
'" />
<xsl:choose>
<xsl:when test="contains($projNumber,$crlf)">
<xsl:value-of select="substring-before($projNumber,$crlf)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$projNumber"/>
</xsl:otherwise>
</xsl:choose>
This can be written as a function but I don't know how to do it, maybe someone can guide but there you go. A better approach that a colleague of mine suggested is to escape the CR and directly use it in substring function this would avoid all those variables in the first place.
Thanks again.
Here's the code again, now with a function getFirstLine.
Note the addtional namespace that is needed.
Also note that this does require XSLT 2.0 (xsl:function is not available in 1.0).
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:f="http://temp.com/functions">
<xsl:output method="text"/>
<xsl:template match="//project/text()">
<xsl:value-of select="f:getFirstLine(.)"/>
</xsl:template>
<xsl:function name="f:getFirstLine">
<xsl:param name="input"/>
<xsl:variable name="afterLeadingWS" select="substring-after($input, substring-before($input,substring-before(normalize-space($input), ' ')))"/>
<xsl:choose>
<xsl:when test="contains($afterLeadingWS, '
')">
<xsl:value-of select="substring-before($afterLeadingWS, '
')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$afterLeadingWS"/>
</xsl:otherwise>
</xsl:choose>
</xsl:function>
</xsl:stylesheet>
here i have pasted a sample xml of 50G, earlier i used fetch the data from this below tag with the help of using crlf but now i want to fetch by using line feed ,because i need data correctly what if i ask like suppose i want linefeed 1 content means AE012345677890
similarly line feed 2 means it should fetch Bank code by using xslt how do i can call line feed .
<local>
<message>
<block4>
<tag>
<name>50G</name>
<value>AE012345677890
Bank code
country name
country code</value>
</tag>
</block4>
</message>
</local>
output required :
AE012345677890,Bank code,country name,country code
It's obviously bad use of XML. The point of XML is that you shouldn't need any other parsing and here you do need one, namely splitting on newline. Anyway, when you already have that, you can split on newline using the core XPath functions substring-before and substring-after.
First line should be something like
substring-before(value, '
')
(that's an xpath expression, so you have to put it into or similar tag) and the remaining lines should be
substring-after(value, '
')
You can combine these two, so second line is
substring-before(substring-after(value, '
'), '
')
third line is
substring-before(substring-after(substring-after(value, '
'), '
'), '
')
etc.
PS: I am not sure whether you need to use
or \n for newline.
Depending on the value space for the different constituent types (e.g. if it is known that they don't contain a space), one of these simple XSLT 1.0 solutions may be what you need:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="value">
<xsl:value-of select=
"translate(., '
', ',')"/>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
Produces:
AE012345677890,Bankcode,countryname,countrycode
And this transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="value">
<xsl:value-of select=
"normalize-space(translate(., '
', ','))"/>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
produces:
AE012345677890, Bank code, country name, country code
If none of these two XSLT 1.0 transformation satisfies your requirements, you may need to perform a trim operation. There is a trim function/template in FXSL -- ready to use.
II. A quick XSLT 2.0 solution:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="value">
<xsl:variable name="vLines" select="tokenize(., '
?
')"/>
<xsl:for-each select="$vLines">
<xsl:value-of select=
"translate(replace(., '(^[ \t\r]+)|([ \t\r]+$)', '~~'), '~', '')"/>
<xsl:if test="not(position() eq last())">,</xsl:if>
</xsl:for-each>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
produces exactly the wanted result:
AE012345677890,Bank code,country name,country code
If you're using XSLT 2.0, you can also do this using the tokenize function:
<xsl:template match="value">
<!-- loop through each segment that's before a line break, output
its normalised value and add a comma if required -->
<xsl:for-each select="tokenize(., '
')">
<xsl:value-of select="normalize-space(current())"/>
<xsl:if test="not(position()=last())">,</xsl:if>
</xsl:for-each>
</xsl:template>
This produces the desired result:
AE012345677890,Bank code,country name,country code
(As Dimitre Novatchev points out below, it will also collapse multiple white space, ie: spaces and tabs inside each line, into one single space, so you might want to experiment and see if that's okay with your data)
If you are limited to XSLT 1.0, you may be able to implement the EXSLT library which also contains tokenize (see the tokenize page and click on "How To" in the upper lefthand menu for more information on implementing the library).
I am trying to work with this RSS feed.
I would like to use XSL to keep only the first paragraph of the description field. I have read up on how to target only certain children of an XML structure, but I think because the paragraph tags in the RSS feed are added as < and > they don't seem to work when doing something like this:
<xsl:value-of select="description/p[position() = 1]" disable-output-escaping="yes"/>
Ideally I would like to select only the text between the paragraph tags and discard them completely.
Any help would really be appreciated.
Use this transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes"/>
<xsl:template match="/*/channel/item/description">
<xsl:value-of select=
"substring-before(substring-after(., '<P>'), '</P>')
"/>
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>