How to fix a special character in XSLT - xslt

I am dealing with below XML where I need to remove a special character in firstname. é in (Andrés) not sure what is this character is actually called. If I process firstname as is it's failing in the Vendor system
<?xml version="1.0" encoding="UTF-8"?>
<reportentry>
<reportdata>
<id>12345</id>
<firstname>Andrés</firstname>
<lastname>Williams</lastname>
</reportdata>
</reportentry>
I simply tried replace function which is working, below is the code. Not sure is there any better way to deal with it ? any suggestions ?
<xsl:value-of select="replace($string1, 'é', 'e')"/>
Full code
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">
<xsl:variable name="string1" select="/reportentry/reportdata/firstname"/>
<xsl:variable name="comma" select="','"/>
<xsl:output method="text" omit-xml-declaration="yes"/>
<xsl:template match="/reportentry">
<xsl:value-of select="reportdata/id"/>
<xsl:value-of select="$comma"/>
<xsl:value-of select="replace($string1, 'é', 'e')"/>
<xsl:value-of select="$comma"/>
<xsl:value-of select="reportdata/lastname"/>
</xsl:template>
</xsl:stylesheet>
I expected result as 12345,Andres,Williams

You can strip most diacritics by using normalize-unicode() to convert the string to decomposed normal form (NFD), and then using replace() to remove all "non-spacing mark" characters (category Mn).
So replace(normalize-unicode(xxx, 'NFD'), '\p{Mn}', '')
Not tested.
But it would be better to modernise the receiving application so it can handle international names...

Related

XSLT - Get String between commas

How can I get the value 'four' in XSLT?
<root>
<entry>(one,two,three,four,five,six)</entry>
</root>
Thanks in advance.
You didn't specify the XSLT version, so I assume version 2.0.
I also assume that word four is only a "marker", stating from which place
take the result string (between the 3rd and 4th comma).
To get the fragment you want, you can:
Use tokenize function to "cut" the whole content of entry
into pieces, using a comma as the cutting pattern.
Take the fourth element of the result array.
This expression can be used e.g. in a template matching entry.
So the example script can look like below:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="UTF-8" indent="yes" />
<xsl:template match="entry">
<xsl:copy>
<xsl:value-of select="tokenize(., ',')[4]"/>
</xsl:copy>
</xsl:template>
<xsl:template match="#*|node()">
<xsl:copy><xsl:apply-templates select="#*|node()"/></xsl:copy>
</xsl:template>
</xsl:transform>
For your input XML it gives:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<entry>four</entry>
</root>

Handling < > in XSLT 1.0

I have a problem, when trying to read a structure having < > in source XML.
Input Structure -
<?xml version="1.0" encoding="UTF-8"?>
<RecordsData>
<RecordsData>
<UID><RecordsData xmlns=""><RecordsData><UID>200</UID><RID>Test-1</RID><Date>20142812</Date><Status>N</Status></RecordsData></RecordsData></UID>
</RecordsData>
</RecordsData>
Expected Output Structure (there are two requirements) -
One is just conversion of < >into well formed XML tags.
<?xml version="1.0" encoding="UTF-8"?>
<RecordsData>
<RecordsData>
<UID><RecordsData xmlns=""><RecordsData><UID>200</UID><RID>Test-1</RID><Date>20142812</Date><Status>N</Status></RecordsData></RecordsData></UID>
</RecordsData>
</RecordsData>
Second is extraction of whole data inside UID tag with output as only below -
<RecordsData xmlns=""><RecordsData><UID>200</UID><RID>Test-1</RID><Date>20142812</Date><Status>N</Status></RecordsData></RecordsData>
I am able to get second output if I have first one in hand. But struggling to get first output from Input over last few days after searching forum extensively and being very new to XSLT.
If we can directly get second output from input source - it's actually what is expected solution. For above - I just tried to break down problem into steps.
Any of experts can you please help!
Thanks,
Conversion is easy, extraction is not.
To convert the escaped markup to real markup, simply disable the escaping when writing the node to the result tree, for example:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="UID">
<xsl:copy>
<xsl:value-of select="." disable-output-escaping="yes"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Ideally, you would use the resulting XML file to extract any data from the escaped portion. Otherwise you would have to apply string functions for this purpose, since the escaped text is not XML.
However, in your example, you don't want to extract anything particular from the data, just isolate it and convert it to a stand-alone markup document. This can be easily accomplished by:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<xsl:value-of select="RecordsData/RecordsData/UID" disable-output-escaping="yes"/>
</xsl:template>
</xsl:stylesheet>

Find node containing the most recent date when date needs converted to valid date format

I need an xPath to be used in a global variable which will select the 'Policy' node with the most recent dateTime (2014-12-02-04:00). Unfortanately the Time delimeter is a dash instead of 'T' so I can't use max() straight away. If I try to use substring or translate to remove the dashes and colon to simply compare numbers I get the error which states that there cannot be more that one sequence in those functions.
Is there a way to evaluate PolicyEffectiveDate from the root node when it is in 2014-12-02-04:00 format?
/Policies/PolicySummary/Policy[2]/PolicyEffectiveDate
XSLT 2.0 is OK. Also, note that I don't have control over the XML format. Thanks.
Given sample XML of:
<?xml version="1.0" encoding="UTF-8"?>
<Policies>
<PolicySummary>
<Policy>
<PolicyNumber>123</PolicyNumber>
<PolicyEffectiveDate>2014-06-01-04:00</PolicyEffectiveDate>
</Policy>
<Policy>
<PolicyNumber>1234</PolicyNumber>
<PolicyEffectiveDate>2014-12-02-04:00</PolicyEffectiveDate>
</Policy>
<Policy>
<PolicyNumber>12345</PolicyNumber>
<PolicyEffectiveDate>2014-08-02-04:00</PolicyEffectiveDate>
</Policy>
</PolicySummary>
</Policies>
You can simply sort the policies by their "dates" as text. For example:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:for-each select="Policies/PolicySummary/Policy">
<xsl:sort select="PolicyEffectiveDate" data-type="text" order="descending"/>
<xsl:if test="position()=1">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
will return:
<?xml version="1.0" encoding="utf-8"?>
<Policy>
<PolicyNumber>1234</PolicyNumber>
<PolicyEffectiveDate>2014-12-02-04:00</PolicyEffectiveDate>
</Policy>
in your example.

XSL Transform, select namespace

I'm new with XSL, but it's ok, but it's the first time I need to do something with namespace, and I'm totally out, can someone explain how to do this :
I have an XHTML like this :
<?xml version="1.0" encoding="ISO-8859-1" ?>
<?xml-stylesheet type="text/xsl" href="5C.xslt"?>
<!DOCTYPE rdf:RDF SYSTEM "http://purl.org/dc/schemas/dcmes-xml20000714.
dtd">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:dcterms="http://purl.org/dc/terms/">
<rdf:Description rdf:about="MyJPeg.jpg">
<dc:title>Find Info</dc:title>
<dc:contributor>Myself</dc:contributor>
<dcterms:created>2013-12-11</dcterms:created>
<dcterms:issued>2013-12-23</dcterms:issued>
</rdf:Description>
</rdf:RDF>
I need to validate if the issued date if = to 2013-10-10 (answer no)
My XSLT is :
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xhtml="http://www.w3.org/1999/xhtml">
<xsl:output method="html" version="1.0" encoding="ISO-8859-1" indent="yes"/>
<xsl:template match="*">
<html><body><pre>
<xsl:value-of select="rdf/issued"/>
<xsl:if test="xxx = '2013-10-10' ">
</xsl:if>
</pre></body>
</html>
</xsl:template>
</xsl:stylesheet>
So I try to have ther value with this line :
<xsl:value-of select="rdf/issued"/>
(to see if I got it)
And to validate with this one :
<xsl:if test="xxx = '2013-10-10' ">
But I'm new with name space and I can't find out how to get my value,
Can someone help me ?
thanks
Question #2, the solution works, but :
If I want to validate if the date is HIGHER than instead of equal, how I can do that ? (I replace = by >), and I change my date to be higher and lower, and each time it doesn't work
<xsl:if test="rdf:Description/dcterms:issued > '2001-01-01' ">
Good job
</xsl:if>
What's wrong ?
thanks
In XML, an element with a namespace if different to an element with no namespace. For example, despite having the same "local" name of "RDF" the following two elements are different.
<RDF>Test</RDF>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">Test</RDF>
To access elements within a namespace in XSLT, you first have to declare the relevant namespaces in your XSTL
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xhtml="http://www.w3.org/1999/xhtml"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dcterms="http://purl.org/dc/terms/">
Then, where you have an xpath expression that refers to elements, you need to add in the prefix
<xsl:value-of select="rdf:Description/dcterms:issued"/>
(I took it as a typo in your question, but "issued" is a child of "Description" in your XML sample!).
Try this XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xhtml="http://www.w3.org/1999/xhtml"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dcterms="http://purl.org/dc/terms/">
<xsl:output method="html" version="1.0" encoding="ISO-8859-1" indent="yes"/>
<xsl:template match="rdf:RDF">
<html><body><pre>
<xsl:value-of select="rdf:Description/dcterms:issued"/>
<xsl:if test="rdf:Description/dcterms:issued = '2013-10-10' ">
</xsl:if>
</pre></body>
</html>
</xsl:template>
</xsl:stylesheet>
It is worth mentioning that the namespace prefix ("rdf:" in this case), does not have to be the same in the XML as it is in the XSLT. It is the namespace URI ("http://www.w3.org/1999/02/22-rdf-syntax-ns#") that has to match.

How to print < and > symbols which are part of text..?

I just can't figure out a way to output string something like :
<xml version="1.0" encoding="UTF-8">
this is what i tried:
<xsl:variable name="lessThan" select="<"/>
<xsl:variable name="GreaterThan" select=">"/>
<xsl:value-of select="$lessThan"/>
<xsl:text>xml version="1.0" encoding="UTF-8"</xsl:text>
<xsl:value-of select="$GreaterThan"/>
but this is the output i'm getting:
<xml version="1.0" encoding="UTF-8">
I also tried doin something like this:
<xsl:text><xml version="1.0" encoding="UTF-8"></xsl:text>
but the editor simply doesn't let me do this.It throws an error to match with end tag
PS:I am not well versed in xslt so Do please reply even if the question sounds naive.
try this:
<xsl:text disable-output-escaping="yes"><xml version="1.0" encoding="UTF-8"></xsl:text>
To make your test xslt working you can use disable-output-escaping = "yes"
Changed xlst:
<xsl:variable name="lessThan" select="'<'"/>
<xsl:variable name="GreaterThan" select="'>'"/>
<xsl:value-of disable-output-escaping = "yes" select="$lessThan"/>
<xsl:text>xml version="1.0" encoding="UTF-8"</xsl:text>
<xsl:value-of disable-output-escaping = "yes" select="$GreaterThan"/>
Update:
Only a guess you try to generate a xml declaration.
<?xml version="1.0" encoding="utf-8"?>
This should be done with xsl:output
<xsl:output method="xml" encoding="utf-8"/>
You should not be trying to produce the XML declaration manually. It should be generated automatically by the XSLT as long as you specify the output method as XML and do not specify omit-xml-declaration="yes":
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" encoding="utf-8" />
<xsl:template match="/">
<root />
</xsl:template>
</xsl:stylesheet>
When this XSLT is run on any input, the result is:
<?xml version="1.0" encoding="utf-8"?>
<root />
Put this <xsl:text disable-output-escaping="yes"><</xsl:text>