Removing line break in CSV output - xslt

I am converting an ASN IDOC from SAP to CSV format but want to get rid of an empty line that is occuring between the header and the content.
My 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:output method="text" encoding="UTF-8" indent="no" omit-xml-declaration="yes"/>
<xsl:template match="/">
<xsl:call-template name="printHeader"/>
<xsl:apply-templates select="DELVRY05/IDOC/E1EDL20/E1EDL24[LFIMG > 0]"/>
</xsl:template>
<xsl:template name="printHeader">
<xsl:text>ProductCode,Description,Invoice,Invoice Date,Batch,Expires,Barcode,Quantity
</xsl:text>
</xsl:template>
<xsl:template match="E1EDL24">
<xsl:value-of select="MATNR"/><xsl:text>,</xsl:text>
<xsl:value-of select="ARKTX"/><xsl:text>,</xsl:text>
<xsl:text>,</xsl:text><!--Invoice is empty-->
<xsl:text>,</xsl:text><!--Invoice date is empty-->
<xsl:value-of select="CHARG"/><xsl:text>,</xsl:text>
<xsl:value-of select="VFDAT"/><xsl:text>,</xsl:text>
<xsl:value-of select="EAN11"/><xsl:text>,</xsl:text><!--Barcode-->
<xsl:value-of select="LFIMG"/><xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>
The CSV output:
Row 2 is blank and I need to remove it, can someone help please?
Thank you.

Hy Jack,
Maybe it's because of the
at the end of this line :
<xsl:text>ProductCode,Description,Invoice,Invoice Date,Batch,Expires,Barcode,Quantity
</xsl:text>
?

Related

Process all files in a directory and create a file according to file-name

I have a working XSLT-transformation that I need to apply to all files in the specified directory:
<?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"
xmlns:tei ="http://www.tei-c.org/ns/1.0"
exclude-result-prefixes="xs"
version="3.0">
<xsl:strip-space elements="*"/>
<xsl:output method="text" indent="yes"/>
<xsl:output omit-xml-declaration="yes"/>
<xsl:variable name="files" select="collection('C:\Users\KW\Desktop\Interim_56_zerlegt')"/>
<xsl:template match="/">
<xsl:result-document href="Interim_56_zerlegt/test.txt" method="text">
Kuerzel; AT/NT; Stelle
<xsl:apply-templates select="//note"></xsl:apply-templates>
</xsl:result-document>
</xsl:template>
<xsl:template match="//note">
<xsl:choose>
<xsl:when test="child::*[1][self::ref[#type='biblical']]">
<xsl:for-each select="child::*[#type='biblical']/#cRef">
<xsl:value-of select="."/>
<xsl:text>;</xsl:text>
</xsl:for-each>
<xsl:text></xsl:text>
<xsl:text>test;</xsl:text>
<xsl:value-of select="."/>
<xsl:text>
</xsl:text>
</xsl:when>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
I have a folder of 56 files that I want to run this transformation on.
So I managed to create a file for one file (<xsl:result-document href='Interim_56_zerlegt') and now I need to do this for "every file" in there (technically only XML but there's nothing else in there) Is there a way to do this?
Use an initial template
<xsl:param name="files" select="uri-collection('file:///C:/Users/KW/Desktop/Interim_56_zerlegt/?select=*.xml')"/>
<xsl:template name="xsl:initial-template">
<xsl:apply-templates select="$files ! doc(.)"/>
</xsl:template>
and start Saxon (?) with e.g -it.
You will also need to adjust the href="Interim_56_zerlegt/test.txt" to e.g. href="Interim_56_zerlegt/result-{position()}.txt" or perhaps href="{document-uri() => replace('\.xml$', '.txt')}".

XSL 1.0 If not like

I'm using XSL to create a PDF document template, and don't want certain fields to display if the line value is zero.
I have tried
<xsl:if test="line_value != 0">
<xsl:with-param name="value" select="unit_quantity"/>
</xsl:if>
But this doesn't work. I think because line_value is of the format £0.00.
I'm trying to get it to do line_value NOT LIKE '£0.00', but I don't think that's the correct syntax for XSL.
I am assuming that below is your XML:
INPUT:
<?xml version="1.0" encoding="utf-8" ?>
<body>
<line_value>£0.00</line_value>
<line_value>£1.00</line_value>
<line_value>£0.00</line_value>
<line_value>£2.00</line_value>
<line_value>£0.00</line_value>
<line_value>£5.00</line_value>
<line_value>£0.00</line_value>
<line_value>£1.00</line_value>
</body>
XSLT:
<?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="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<root>
<xsl:for-each select="body/line_value">
<xsl:if test="number(translate(., '£', '')) != 0">
<num>
<xsl:value-of select="."/>
</num>
</xsl:if>
</xsl:for-each>
</root>
</xsl:template>
</xsl:stylesheet>

<xsl:for-each> repeats first row

Below is what my XML looks like. I have also copied XSLT and output below. My problem is that, the output is always repeating the same first row. If I add more rows to input XML file then first row would repeat in output file for that many number of rows added. What could be the reason?
XML:
<Loans>
<Loan>
<loan_number>123</loan_number>
<loan_aqn_date>08-01-2016</loan_number>
</Loan>
<Loan>
<loan_number>456</loan_number>
<loan_aqn_date>10-01-2016</loan_number>
</Loan>
<Loan>
<loan_number>789</loan_number>
<loan_aqn_date>12-01-2016</loan_number>
</Loan>
</Loans>
Output:
loan_number|loan_aqn_date|
123|08-01-2016|
123|08-01-2016|
123|08-01-2016|
XSLT:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" />
<xsl:template match="/">
<xsl:text>loan_number|loan_aqn_date|</xsl:text>
<xsl:for-each select="/Loans/Loan">
<xsl:value-of select="concat(/Loans/Loan/loan_number,'|')" />
<xsl:value-of select="concat(/Loans/Loan/loan_aqn_date,'|')" />
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
You are using an absolute path for "select" inside loop.
Try this:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" />
<xsl:template match="/">
<xsl:text>loan_number|loan_aqn_date|</xsl:text>
<xsl:for-each select="/Loans/Loan">
<xsl:value-of select="concat(loan_number,'|')" />
<xsl:value-of select="concat(loan_aqn_date,'|')" />
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Replacing the <for-each> with a template could make your approach more general.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" />
<xsl:strip-space elements="Loans" /> <!-- Removes surrounding spaces -->
<xsl:template match="/Loans">
<xsl:text>loan_number|loan_aqn_date|
</xsl:text>
<xsl:apply-templates /> <!-- Processes 'Loan' nodes -->
</xsl:template>
<xsl:template match="Loan">
<xsl:value-of select="concat(loan_number, '|', loan_aqn_date,'|')" />
<xsl:text>
</xsl:text> <!-- Adds newlines -->
</xsl:template>
</xsl:stylesheet>
Output:
loan_number|loan_aqn_date|
123|08-01-2016|
456|10-01-2016|
789|12-01-2016|

SOAP to XML transformation

I am trying to do SOAP to XML transformation in XSLT.
I have a field called "acctCd" which is under "externalIDGroup" which is an array. SO i need to check the field lenth for "acctCd" if it is more then 10 charatcer i need to trim it to 10 character and if it is less i need to get the valuen as it is. This value can come multiple times.Please let me know where is the issue in my code
INput:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:ClaimsRequest xmlns:ns2="http://example.com">
<externalIDGroup>
<acctCd>plan1 Options</acctCd>
</externalIDGroup>
<externalIDGroup>
<acctCd>Plan2 Options</acctCd>
</externalIDGroup>
</ns2:ClaimsRequest>
</soap:Body>
</soap:Envelope>
XSL Code:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:dp="http://www.datapower.com/extensions"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
extension-element-prefixes="dp" exclude-result-prefixes="dp"
version="1.0">
<xsl:template match="/">
<ClaimsRequest>
<xsl:for-each select="//externalIDGroup">
<xsl:variable name="acCode">
<xsl:value-of select="acctCd"/>
</xsl:variable>
<xsl:variable name="acCode1">
<xsl:choose>
<xsl:when test="string-length($acCode) > 10">
<xsl:value-of select="substring($acCode, 1,10)"/>
</xsl:when>
<xsl:otherwise><xsl:value-of select="$acCode"/></xsl:otherwise>
</xsl:choose>
</xsl:variable>
<claimDetail>
<accountCode><xsl:value-of select="acctCd1"/></accountCode>
</claimDetail>
</xsl:for-each>
</ClaimsRequest>
</xsl:template>
</xsl:stylesheet>
Desired output :
<ClaimsRequest>
<claimDetail>
<accountCode>plan1 Opti</accountCode>
</claimDetail>
<claimDetail>
<accountCode>Plan2</accountCode>
</claimDetail>
</ClaimsRequest>
I don't understand how you derived your desired output from the input. I suspect that all you need to do is :
<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="/">
<ClaimsRequest>
<xsl:for-each select="//externalIDGroup">
<claimDetail>
<accountCode>
<xsl:value-of select="substring(acctCd, 1, 10)"/>
</accountCode>
</claimDetail>
</xsl:for-each>
</ClaimsRequest>
</xsl:template>
</xsl:stylesheet>

XSLT manipulate text scattered across various nodes

Input file as follows:
<?xml version="1.0" encoding="UTF-8"?>
<!-- lower UPPER case -->
<document>
<rubbish> rubbish </rubbish>
<span class='lower'>
lower
<span class='upper'> upper </span>
case
</span>
</document>
Wanted output:
lower UPPER case
I know how to get the text included in the outer span with value-of, but this also
includes the string "upper" unchanged which is not what I want. I do not know how
to manipulate the text in the inner span and insert it in the middle of
the other text.
Failed attempt:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="text" indent="no"/>
<xsl:template match="/">
<xsl:for-each select="//span[#class = 'lower']">
<xsl:if test="span/#class = 'upper'">
<xsl:text>do something</xsl:text> <!--TO DO -->
</xsl:if>
<xsl:value-of select="."/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
You need to take a recursive approach here, for example:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output method="text" encoding="UTF-8"/>
<xsl:template match="text()[parent::span]">
<xsl:choose>
<xsl:when test="../#class='upper'">
<xsl:value-of select="translate(., 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="." />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
To understand how this works, read up on built-in template rules: http://www.w3.org/TR/xslt/#built-in-rule
The following approach does away with the <choose> and completely pushes the problem down to the match expression:
<?xml version="1.0" encoding="UTF-8"?>
<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="text()"/>
<xsl:template match="text()[parent::span[#class = 'upper']]">
<xsl:value-of select="translate(., 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/>
</xsl:template>
<xsl:template match="text()[parent::span[#class = 'lower']]">
<xsl:value-of select="translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>
</xsl:template>
</xsl:stylesheet>