XSLT copy/copy-of without keeping namespaces - xslt

Hi I have issue in the default namespace declaration. output xml elements are appended with the default namespace.
The input XML look like
<m:Request xmlns:m="http://www.NeededNamespace/1.4.0">
<Details>
<Records>50</Records>
<Start>1</Start>
<sortName>sortName</sortName>
</Details>
<search>
<criteria>
<comparative>
<Comparative>exactMatch</Comparative>
</comparative>
<name>STATECODE</name>
<value>CO</value>
</criteria>
<criteria>
<comparative>
<Comparative>exactMatch</Comparative>
</comparative>
<name>Version</name>
<value>4.0</value>
</criteria>
<criteria>
<comparative>
<Comparative>contains</Comparative>
</comparative>
<name>LEGALNAME</name>
<value>Citizens State Bank</value>
</criteria>
</search>
</m:Request>
The XSLT look like
<xsl:stylesheet version="1.0" exclude-result-prefixes="t" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:t="http://www.NotRequirednamespace.com">
<xsl:output indent="yes" method="xml" encoding="utf-8" omit-xml-declaration="yes"/>
<xsl:strip-space elements="*"/>
<!--Stylesheet to remove all namespaces from a document-->
<!--NOTE: this will lead to attribute name clash, if an element contains
two attributes with same local name but different namespace prefix-->
<!--Nodes that cannot have a namespace are copied as such-->
<xsl:template match="/">
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap:Header>
<xys:To xmlns:xys="http://services.xys.com/framework/xysHeader/v2">
<xys:version>9.0</xys:version>
<xys:serviceName>DetailsManagement</xys:serviceName>
<xys:QOS>DEFAULT</xys:QOS>
<xys:operation>GetDetails</xys:operation>
</xys:To>
<ConsumerInfo xmlns="http://services.xys.com/framework/xysHeader/v2">
<xysApplicationName>SAP</xysApplicationName>
<xysCheckPermission>-1</xysCheckPermission>
<xysConsumerPlatform>CS</xysConsumerPlatform>
<xysLanguage>en</xysLanguage>
<xysLocale>US</xysLocale>
<xysLogLevel>false</xysLogLevel>
</ConsumerInfo>
<HeaderMetadata xmlns="http://services.xys.com/framework/xysHeader/v2">
<metadataContractVersion>2.0</metadataContractVersion>
<Id>414</Id>
<Timestamp>2014-11-20T14:17:30.908-0500</Timestamp>
</HeaderMetadata>
<xys:favouriteSausage xmlns:xys="http://services.xys.com/framework/xysHeader/v2">cumberland</xys:favouriteSausage>
</soap:Header>
<soap:Body>
<GetDetails xmlns="http://www.NeededNamespace/1.4.0">
<Message id="" version="" bodyType="FS-XML" timeStampCreated="2015-10-11T10:15:25.9144403-04:00" sourceLogicalId="" xmlns="http://www.ibm.com/industries/xys">
<ACGroup bodyCategory="" TPMode="RespondError"/>
<COMMAND>
<xsl:apply-templates/>
</COMMAND>
</Message>
</GetDetails>
</soap:Body>
</soap:Envelope>
</xsl:template>
<!--template to copy elements-->
<xsl:template match="*">
<xsl:element name="{local-name()}" namespace="http://www.NeededNamespace/1.4.0">
<xsl:apply-templates select="#* | node()"/>
</xsl:element>
</xsl:template>
<!--template to copy attributes-->
<xsl:template match="#*">
<xsl:attribute name="{local-name()}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
<!--template to copy the rest of the nodes-->
<xsl:template match="comment() | text() | processing-instruction()">
<xsl:copy/>
</xsl:template>
</xsl:stylesheet>
The output XML what i am getting is
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap:Header>
<xys:To xmlns:xys="http://services.xys.com/framework/xysHeader/v2">
<xys:version>9.0</xys:version>
<xys:serviceName>DetailsManagement</xys:serviceName>
<xys:QOS>DEFAULT</xys:QOS>
<xys:operation>GetDetails</xys:operation>
</xys:To>
<ConsumerInfo xmlns="http://services.xys.com/framework/xysHeader/v2">
<xysApplicationName>SAP</xysApplicationName>
<xysCheckPermission>-1</xysCheckPermission>
<xysConsumerPlatform>CS</xysConsumerPlatform>
<xysLanguage>en</xysLanguage>
<xysLocale>US</xysLocale>
<xysLogLevel>false</xysLogLevel>
</ConsumerInfo>
<HeaderMetadata xmlns="http://services.xys.com/framework/xysHeader/v2">
<metadataContractVersion>2.0</metadataContractVersion>
<Id>414</Id>
<Timestamp>2014-11-20T14:17:30.908-0500</Timestamp>
</HeaderMetadata>
<xys:favouriteSausage xmlns:xys="http://services.xys.com/framework/xysHeader/v2">cumberland</xys:favouriteSausage>
</soap:Header>
<soap:Body>
<GetDetails xmlns="http://www.NeededNamespace/1.4.0">
<Message xmlns="http://www.ibm.com/industries/xys" id="" version="" bodyType="FS-XML" timeStampCreated="2015-10-11T10:15:25.9144403-04:00" sourceLogicalId="">
<ACGroup bodyCategory="" TPMode="RespondError"/>
<COMMAND>
<Request xmlns="http://www.NeededNamespace/1.4.0">
<Details>
<Records>50</Records>
<Start>1</Start>
<sortName>sortName</sortName>
</Details>
<search>
<criteria>
<comparative>
<Comparative>exactMatch</Comparative>
</comparative>
<name>STATECODE</name>
<value>CO</value>
</criteria>
<criteria>
<comparative>
<Comparative>exactMatch</Comparative>
</comparative>
<name>Version</name>
<value>4.0</value>
</criteria>
<criteria>
<comparative>
<Comparative>contains</Comparative>
</comparative>
<name>LEGALNAME</name>
<value>Citizens State Bank</value>
</criteria>
</search>
</Request>
</COMMAND>
</Message>
</GetDetails>
</soap:Body>
</soap:Envelope>
But in the result I am getting the element as
<Request xmlns="http://www.NeededNamespace/1.4.0">
But i want the result tag as like below
<Request>
I dont want to redeclare the namespace which is already declared in the root tag of the same. I have tried all the option i have known and tried for last few days. can you please help me on this.

The input element has expanded name (local-part="Request", namespace="http://www.NeededNamespace/1.4.0"). If you don't want the output Request element to have a namespace declaration, then presumably you want it to be in the same namespace as its parent, that is you want its expanded name to be (local-part="Request", namespace="http://www.ibm.com/industries/xys"). An xsl:copy or xsl:copy-of instruction will never (even in 2.0) change the expanded name of the element being copied. So you can't achieve your desired output using xsl:copy or xsl:copy-of. You will need to create a new element with the same local name but a different namespace from the original, using <xsl:element name="{local-name()}" namespace="http://www.ibm.com/industries/xys"/>.

Related

Not select a particular node child Elements in xslt using not

My XML is below. Is it possible to do this in same XSLT?
<response context="XXXX" type="abcd" errorCode="0" >
<output>
<Applicants>
<Applicant>
<IndividualEmployments/>
<Addresses/>
</Applicant>
</Applicants>
<Assets>
<Asset id="12345"></Asset>
</Assets>
<Liabilities>
<Liability id="8765"></Liability>
</Liabilities>
</output>
Desired output should be like below. I want two response nodes, one with Assets and the other with Liabilities.
<response context="XXXX" type="abcd" errorCode="0">
<output>
<Applicants>
<Applicant>
<IndividualEmployments/>
<Addresses/>
</Applicant>
</Applicants>
<Assets>
<Asset id="12345"></Asset>
</Assets>
</output>
<response context="XXXX" type="abcd" errorCode="0">
<output>
<Applicants>
<Applicant>
<IndividualEmployments/>
<Addresses/>
</Applicant>
</Applicants>
<Liabilities>
<Liability id="8765"></Liability>
</Liabilities>
</output>
You need to process the response element and output it twice, making sure the content is different, for instance by passing a parameter:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
expand-text="yes">
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="response">
<xsl:next-match>
<xsl:with-param name="exclude" tunnel="yes" select="descendant::Liabilities"/>
</xsl:next-match>
<xsl:next-match>
<xsl:with-param name="exclude" tunnel="yes" select="descendant::Assets"/>
</xsl:next-match>
</xsl:template>
<xsl:template match="output">
<xsl:param name="exclude" tunnel="yes"/>
<xsl:copy>
<xsl:apply-templates select="#*, node() except $exclude"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
If needed or wanted you can of course wrap each xsl:next-match I have in an xsl:result-document.

Multiple transformations to an xml file using xslt 1

Newbie to this site and using xslt but running into a roadblock transforming a SSRS 2008v2 rendered xml file into another XSL raw format for a 3rd Party EDI transfer. I've been searching this site and others for a while now, but struggling putting it all together.I'm starting with the following raw xml data;
<Invoices xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.spscommerce.com/RSX" xsi:schemaLocation="http://www.spscommerce.com/RSX http://tfl- sql01/ReportServer_SQL2012? %2FTesting%2FINTest&rs%3ACommand=Render&rs%3AFormat=XML&rs%3ASessionID= jn5ugdirg4m02nmodnm0hynq&rc%3ASchema=True" Name="INTest">
<Invoices1> ***need to remove***
<ivhID_Collection> ***need to remove***
<Invoices>...</Invoices>
<Invoices>...</Invoices>
<Invoices>
<Invoice>
<Header1>
<InvoiceHeader>...</InvoiceHeader>
<PaymentTerms>...</PaymentTerms>
<Dates>...</Dates>
<Address>...</Address>
<References>...</References>
<ChargesAllowances>...</ChargesAllowances>
<LineItem_Collection> ***need to remove and replace with </Header>***
<LineItem>
<InvoiceLine>...</InvoiceLine>
<ProductOrItemDescription>...</ProductOrItemDescription>
</LineItem>
<LineItem>
<InvoiceLine>...</InvoiceLine>
<ProductOrItemDescription>...</ProductOrItemDescription>
</LineItem>
</LineItem_Collection> ***need to remove***
<Summary>...</Summary>
</Header1> ***need to remove***
</Invoice>
</Invoices>
<Invoices>...</Invoices>
<Invoices>...</Invoices>
<Invoices>...</Invoices>
/ivhID_Collection> ***need to remove***
</Invoices1> ***need to remove***
</Invoices>
Trying to get it in this structure instead;
<Invoices xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.spscommerce.com/RSX" xsi:schemaLocation="http://www.spscommerce.com/RSX http://tfl-sql01/ReportServer_SQL2012?%2FTesting%2FINDoItBest%20v7&rs%3ACommand=Render&rs%3AFormat=XML&rs%3ASessionID=jn5ugdirg4m02nmodnm0hynq&rc%3ASchema=True" Name="INDoItBest v7">
<Invoices>...</Invoices>
<Invoices>...</Invoices>
<Invoices>
<Invoice>
<Header>
<InvoiceHeader>...</InvoiceHeader>
<PaymentTerms>...</PaymentTerms>
<Dates>...</Dates>
<Address>...</Address>
<References>...</References>
<ChargesAllowances>...</ChargesAllowances>
</Header>
<LineItem>
<InvoiceLine>...</InvoiceLine>
<ProductOrItemDescription>...</ProductOrItemDescription>
</LineItem>
<LineItem>
<InvoiceLine>...</InvoiceLine>
<ProductOrItemDescription>...</ProductOrItemDescription>
</LineItem>
<Summary>...</Summary>
</Invoice>
</Invoices>
<Invoices>...</Invoices>
<Invoices>...</Invoices>
<Invoices>...</Invoices>
</Invoices>
I made some progress using this style sheet, but am stuck on the regrouping of the Header tag and the display of the element namespace.
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:t="http://www.spscommerce.com/RSX"
exclude-result-prefixes="t">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<!--rule to suppress the undesired nodes-->
<xsl:template match="t:Invoices1|t:ivhID_Collection">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="t:LineItem_Collection">
<xsl:apply-templates/>
</xsl:template>
<!--<xsl:template match="t:Invoice/t:Header1">
<xsl:apply-templates/>
</xsl:template>-->
<!-- Identity Transform -->
<xsl:template match="t:Header1">
<xsl:copy>
<xsl:element name="Header">
<xsl:apply-templates select="#*|t:InvoiceHeader|t:PaymentTerms|t:Dates|t:Address|t:References|t:ChargesAllowances"/>
</xsl:element>
<xsl:apply-templates select="#*|t:LineItem_Collection|t:Summary"/>
</xsl:copy>
</xsl:template>
<!-- Had to comment out -->
<!--<xsl:template match="t:Invoice/t:Header1">
<xsl:apply-templates/>
</xsl:template>-->
The stylesheet produced most of what I needed, but failed when I tried to remove the Header1 tag (code commented out). Also, struggling to understand why "exclude-result-prefixes" isn't working to remove the namespace from the new xml file.
<Invoices xmlns="http://www.spscommerce.com/RSX" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.spscommerce.com/RSX http://tfl-sql01/ReportServer_SQL2012?%2FTesting%2FINDoItBest%20v7&rs%3ACommand=Render&rs%3AFormat=XML&rs%3ASessionID=jn5ugdirg4m02nmodnm0hynq&rc%3ASchema=True" Name="INDoItBest v7">
<Invoices>...</Invoices>
<Invoices>...</Invoices>
<Invoices>
<Invoice>
<Header1>
<Header xmlns="">
<InvoiceHeader xmlns="http://www.spscommerce.com/RSX">... </InvoiceHeader>
<PaymentTerms xmlns="http://www.spscommerce.com/RSX">... </PaymentTerms>
<Dates xmlns="http://www.spscommerce.com/RSX">...</Dates>
<Address xmlns="http://www.spscommerce.com/RSX">...</Address>
<References xmlns="http://www.spscommerce.com/RSX">...</References>
<ChargesAllowances xmlns="http://www.spscommerce.com/RSX">... </ChargesAllowances>
</Header>
<LineItem>
<InvoiceLine>...</InvoiceLine>
<ProductOrItemDescription>...</ProductOrItemDescription>
</LineItem>
<LineItem>
<InvoiceLine>...</InvoiceLine>
<ProductOrItemDescription>...</ProductOrItemDescription>
</LineItem>
<Summary>
<TotalAmount>756.8400</TotalAmount>
<TotalSalesAmount>727.1600</TotalSalesAmount>
<TotalLineItemNumber>2</TotalLineItemNumber>
</Summary>
</Header1>
</Invoice>
</Invoices>
<Invoices>...</Invoices>
<Invoices>...</Invoices>
<Invoices>...</Invoices>
</Invoices>
Any advice or other options would be greatly appreciated!
You've already got a template matching t:Header1 in your XSLT, so you shouldn't add another one matching it, as only one can apply. (In your case, if you did add a template matching t:Invoice\t:Header1 then because of the parent being specified, it would have a higher priority as the one just matching t:Header1 and be used instead).
What you will need to do, is put all the logic in the single template. In this case, all you need to do is remove the xsl:copy from that template to avoid the Header1 being copied to the output tree. Additionally, when you create Header, you are creating it in no namespace, not in the namespace bound to the prefix "t". Therefore, the child elements will be given new namespace declarations because they will still be in that namespace.
One way to do it is simply add a "namespace" attribute to the xsl:element, like so:
<xsl:element name="Header" namespace="http://www.spscommerce.com/RSX">
Alternatively, you can create the element by just doing <Header> but you will need to add a default namespace declaration to the XSLT too, to ensure it gets output in the correct namespace.
Try this XSLT:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:t="http://www.spscommerce.com/RSX"
xmlns="http://www.spscommerce.com/RSX"
exclude-result-prefixes="t">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<!--rule to suppress the undesired nodes-->
<xsl:template match="t:Invoices1|t:ivhID_Collection">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="t:LineItem_Collection">
<xsl:apply-templates/>
</xsl:template>
<!-- Identity Transform -->
<xsl:template match="t:Header1">
<xsl:apply-templates select="#*" />
<Header>
<xsl:apply-templates select="#*|t:InvoiceHeader|t:PaymentTerms|t:Dates|t:Address|t:References|t:ChargesAllowances"/>
</Header>
<xsl:apply-templates select="t:LineItem_Collection|t:Summary"/>
</xsl:template>
</xsl:stylesheet>
As a side note, in your XSLT you were also doing this immediately after creating the Header element
<xsl:apply-templates select="#*|t:LineItem_Collection|t:Summary"/>
This would fail if the Header1 had attributes you wanted to copy, as it is an error to try to add attributes to a parent element after you have created child elements. This is why in my XSLT I have split the statement into two.

XSLT field validation

I have a requirement to validate a field content which is within a 1..N structure, so the data come in pairs of RESULT_ID and RESULT_VALUE.
If "<" is found in Result.Min_Limit characteristic, its value must be put in the Max_Limit characteristic target field and Min_Limit must be cleared out in target structure.
Sample of source structure with data:
<?xml version="1.0" encoding="UTF-8"?>
<TEST>
<RESULTS>
<RESULT>
<D_RESULT>
<D_RESULT_ID>Result.Derived</D_RESULT_ID>
<D_RESULT_VALUE>59W</D_RESULT_VALUE>
</D_RESULT>
<D_RESULT>
<D_RESULT_ID>Result.Min_Limit</D_RESULT_ID>
<D_RESULT_VALUE><=600.0000</D_RESULT_VALUE>
</D_RESULT>
<D_RESULT>
<D_RESULT_ID>Result.Max_Limit</D_RESULT_ID>
<D_RESULT_VALUE/>
</D_RESULT>
<D_RESULT>
<D_RESULT_ID>Result.FailedCriticalLvl</D_RESULT_ID>
<D_RESULT_VALUE>false</D_RESULT_VALUE>
</D_RESULT>
</RESULT>
</RESULTS>
</TEST>
Expected target structure should be as follow:
<?xml version="1.0" encoding="UTF-8"?>
<TEST>
<RESULTS>
<RESULT>
<D_RESULT>
<D_RESULT_ID>Result.Derived</D_RESULT_ID>
<D_RESULT_VALUE>59W</D_RESULT_VALUE>
</D_RESULT>
<D_RESULT>
<D_RESULT_ID>Result.Min_Limit</D_RESULT_ID>
<D_RESULT_VALUE/>
</D_RESULT>
<D_RESULT>
<D_RESULT_ID>Result.Max_Limit</D_RESULT_ID>
<D_RESULT_VALUE><=600.0000</D_RESULT_VALUE>
</D_RESULT>
<D_RESULT>
<D_RESULT_ID>Result.FailedCriticalLvl</D_RESULT_ID>
<D_RESULT_VALUE>false</D_RESULT_VALUE>
</D_RESULT>
</RESULT>
</RESULTS>
</TEST>
I've created a variable to store Min_Limit value if it contains the "<" character, and it works fine when the pointer is still in Min_Limit characteristic.
When it flips to next characteristic (Max_Limit), the variable seems to loose its value and therefore I have no visibility of Min_Limit value anymore to assign the value to Max_Limit characteristic.
Currently, what I have is like the following:
......
<xsl:for-each select="a:D_RESULT">
<D_RESULT>
<D_RESULT_ID>
<xsl:value-of select="a:D_RESULT_ID"/>
</D_RESULT_ID>
<D_RESULT_VALUE>
<xsl:value-of select="a:D_RESULT_VALUE"/>
</D_RESULT_VALUE>
</D_RESULT>
</xsl:for-each>
</RESULT>
... other fields
I've found some interesting conversations here with some approaches I believe would help solving this, but I'm not sure I understood enough to apply to my scenario.
This is one of those XSLT: nested for-each and dynamic variable
Would anyone suggests something to solve this?
Many thanks in advance!
Rafael.
Here's one way you could look at it:
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="D_RESULT_VALUE[../D_RESULT_ID='Result.Min_Limit' and contains(., '<')] ">
<xsl:copy/>
</xsl:template>
<xsl:template match="D_RESULT_VALUE[../D_RESULT_ID='Result.Max_Limit' and contains(../../D_RESULT[D_RESULT_ID='Result.Min_Limit']/D_RESULT_VALUE, '<')] ">
<xsl:copy>
<xsl:value-of select="../../D_RESULT[D_RESULT_ID='Result.Min_Limit']/D_RESULT_VALUE"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Demo: http://xsltransform.net/3NzcBtA

A sequence of more than one item is not allowed as the second argument of concat()

The below xsl works fine if I do not bring in the "other_location_postal_code" field, which is commented here.
This is because there are multiple records if I bring in that field.
How can I have this xsl evaluate each record so it would write this record twice, once for the one "other location postal code" and the other?
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:e="http://www.taleo.com/ws/tee800/2009/01" xmlns:fct="http://www.taleo.com/xsl_functions" exclude-result-prefixes="e fct">
<xsl:output method="xml" encoding="UTF-8" omit-xml-declaration="no"/>
<xsl:param name="OUTBOUND_FOLDER"/>
<xsl:template match="/">
<source>
<xsl:apply-templates select="//e:Requisition"/>
</source>
</xsl:template>
<xsl:template match="e:Requisition">
<xsl:variable name="job_id" select="e:ContestNumber"/>
<xsl:variable name="other_location_postal_code" select="e:JobInformation/e:JobInformation/e:OtherLocations/e:Location/e:NetworkLocation/e:NetworkLocation/e:ZipCode"/>
<job>
<job_id>
<xsl:value-of select="concat('<','![CDATA[',$job_id,']]','>')"/>
</job_id>
<other_location_postal_code>
<xsl:value-of select="concat('![CDATA[',$other_location_postal_code,']]')"/>
</other_location_postal_code>
</job>
</xsl:template>
</xsl:stylesheet>
I want it to come out like so:
<?xml version="1.0" encoding="UTF-8"?>
<source>
<job>
<job_id><![CDATA[15000005]]></job_id>
<other_location_postal_code><![CDATA[77382]]></other_location_postal_code>
</job>
<job>
<job_id><![CDATA[15000005]]></job_id>
<other_location_postal_code><![CDATA[37567]]></other_location_postal_code>
</job>
</source>
The initial XML looks like so:
<?xml version="1.0" encoding="UTF-8"?>
-<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
-<soapenv:Body>
-<ns1:getDocumentByKeyResponse xmlns:ns1="http://www.taleo.com/ws/integration/toolkit/2005/07" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
-<Document xmlns="http://www.taleo.com/ws/integration/toolkit/2005/07">
-<Attributes>
<Attribute name="count">1</Attribute>
<Attribute name="duration">0:00:00.088</Attribute>
<Attribute name="entity">Requisition</Attribute>
<Attribute name="mode">T-XML</Attribute>
<Attribute name="version">http://www.taleo.com/ws/tee800/2009/01</Attribute>
</Attributes>
-<Content>
-<ExportTXML xmlns="http://www.taleo.com/ws/integration/toolkit/2005/07" xmlns:e="http://www.taleo.com/ws/tee800/2009/01">
-<e:Requisition>
<e:ContestNumber>15000005</e:ContestNumber>
-<e:JobInformation>
-<e:JobInformation>
-<e:OtherLocations>
-<e:Location>
<e:ZipCode>77002</e:ZipCode>
</e:Location>
-<e:Location>
<e:ZipCode>77050</e:ZipCode>
</e:Location>
</e:OtherLocations>
</e:JobInformation>
</e:JobInformation>
</e:Requisition>
</ExportTXML>
</Content>
</Document>
</ns1:getDocumentByKeyResponse>
</soapenv:Body>
</soapenv:Envelope>
The error message simply says that an argument to the concat function is a sequence of more than one node. So some of your variable selects two or more nodes and concat expects as single node for each of its arguments. You will need to decide what you want to output, either only the first node with $var[1] or the concatenation with string-join($var, ' ').
Note that you don't need all those attempts to output CDATA section, you can tell the XSLT processor the cdata-section-elements on the xsl:output direction.
As you have now posted more details here is one suggestion to map each ZipCode element to job element:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:e="http://www.taleo.com/ws/tee800/2009/01"
exclude-result-prefixes="e">
<xsl:output indent="yes" cdata-section-elements="job_id other_location_postal_code"/>
<xsl:template match="/">
<source>
<xsl:apply-templates select="//e:OtherLocations/e:Location/e:ZipCode"/>
</source>
</xsl:template>
<xsl:template match="e:ZipCode">
<xsl:apply-templates select="ancestor::e:Requisition">
<xsl:with-param name="zc" select="current()"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="e:Requisition">
<xsl:param name="zc"/>
<job>
<job_id><xsl:value-of select="e:ContestNumber"/></job_id>
<other_location_postal_code><xsl:value-of select="$zc"/></other_location_postal_code>
</job>
</xsl:template>
</xsl:stylesheet>

Modify node text within xsl copy-of

I have a xml document which looks like
<!-- language: lang-xml -->
<?xml version="1.0" encoding="UTF-8"?>
<Request xmlns="fst" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Header>
<AccountServer e-dtype="int">3</AccountServer>
</Header>
<Response>
<ResponseList e-dtype="list">
<Response>
<RequestId e-dtype="string">ServiceOrderGetRef</RequestId>
<RequestObjName e-dtype="string">ServiceOrder</RequestObjName>
<ServiceOrder>
<CreateDt e-dtype="dateTime">2014-03-01 00:00:00</CreateDt>
<CreateWho e-dtype="string">vc</CreateWho>
<WorkflowStartDt e-dtype="dateTime">2014-04-01 00:00:00</WorkflowStartDt>
</ServiceOrder>
</Response>
<Response>
<ComponentList e-dtype="list"/>
<Count e-dtype="int">0</Count>
<RequestId e-dtype="string">ComponentFindRef</RequestId>
<RequestObjName e-dtype="string">Component</RequestObjName>
<TotalCount e-dtype="int">0</TotalCount>
</Response>
<Response>
<Count e-dtype="int">0</Count>
<CustomerContractList e-dtype="list"/>
<RequestId e-dtype="string">CustomerContractRef</RequestId>
<RequestObjName e-dtype="string">CustomerContract</RequestObjName>
<TotalCount e-dtype="int">0</TotalCount>
</Response>
<Response>
<Count e-dtype="int">0</Count>
<ProductList e-dtype="list"/>
<RequestId e-dtype="string">ProductRef</RequestId>
<RequestObjName e-dtype="string">Product</RequestObjName>
<TotalCount e-dtype="int">0</TotalCount>
</Response>
<Response>
<Count e-dtype="int">0</Count>
<NrcList e-dtype="list"/>
<RequestId e-dtype="string">NrcFindRef</RequestId>
<RequestObjName e-dtype="string">Nrc</RequestObjName>
<TotalCount e-dtype="int">0</TotalCount>
</Response>
</ResponseList>
</Response>
</Request>
I am using copy-of function to copy node ServiceOrder within another xml document
I want to modify text of node WorkFlowStartDt and CreateDt and then do a copy-of. How can I do this?
My copied serviceorder node should look like this after modifing text. Below is the result xml
<?xml version="1.0" encoding="UTF-8"?>
<Request>
<Header>
<OperatorName e-dtype="string">ws</OperatorName>
<ApplicationName e-dtype="string">ws</ApplicationName>
</Header>
<CustomerUdtRequest>
<RequestList e-dtype="list">
<LogicalServiceOrder>
<RequestId e-dtype="string">MyExistingOrder</RequestId>
<LogicalServiceOrderPreProcess>
<Fetch e-dtype="boolean">true</Fetch>
<Order>
<AccountInternalId e-dtype="int">12345</AccountInternalId>
<Key>
<OrderId e-dtype="numeric">12345678</OrderId>
</Key>
</Order>
<ServiceOrderList e-dtype="list">
<ServiceOrder xmlns="fst" xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance">
<CreateDt e-dtype="dateTime">2014-03-02 00:00:00</CreateDt>
<CreateWho e-dtype="string">vc</CreateWho>
<WorkflowStartDt e-dtype="dateTime">2014-05-01 00:00:00</WorkflowStartDt>
</ServiceOrder>
</ServiceOrderList>
</LogicalServiceOrderPreProcess>
</LogicalServiceOrder>
</RequestList>
</CustomerUdtRequest>
</Request>
Below is my xslt processor file
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"/>
<xsl:template match="/">
<Request>
<Header>
<OperatorName e-dtype="string">ws</OperatorName>
<ApplicationName e-dtype="string">ws</ApplicationName>
</Header>
<CustomerUdtRequest>
<RequestList e-dtype="list">
<LogicalServiceOrder>
<RequestId e-dtype="string">MyExistingOrder</RequestId>
<LogicalServiceOrderPreProcess> <Order> <AccountInternalId e-dtype="int">
<xsl:value-of
select="/Request/Response/ResponseList/Response/ServiceOrder/AccountInternalId"/>
</AccountInternalId> <Key> <OrderId e-dtype="numeric"> <xsl:value-of select="/Request/Response/ResponseList/Response/ServiceOrder/OrderId"/>
</OrderId>
</Key>
</Order>
<ServiceOrderList e-dtype="list">
<xsl:copy-of select="/Request/Response/ResponseList/Response/ServiceOrder"/>
</ServiceOrderList>
</LogicalServiceOrderPreProcess>
</LogicalServiceOrder>
</xsl:if>
</RequestList>
</CustomerUdtRequest>
</Request>
</xsl:template>
</xsl:stylesheet>
I want to modify text of node WorkFlowStartDt and CreateDt and then do
a copy-of.
That would be an unnecessary complication. You can modify nodes while you add them to the output tree.
Since you essentially want to copy everything "as is" except two nodes, it would be best to start with an identity transform template, then add an "exception" template for the two specific nodes that need modifying (one template for both, since the modification is identical).:
<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"/>
<!-- identity transformation -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="CreateDt | WorkFlowStartDt">
<xsl:copy>
<xsl:value-of select="concat('**', ., '**')"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Added:
In response to the edited question, try this stylesheet:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns="fst"
exclude-result-prefixes="ns">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<Request>
<Header>
<OperatorName e-dtype="string">ws</OperatorName>
<ApplicationName e-dtype="string">ws</ApplicationName>
</Header>
<CustomerUdtRequest>
<RequestList e-dtype="list">
<LogicalServiceOrder>
<RequestId e-dtype="string">MyExistingOrder</RequestId>
<LogicalServiceOrderPreProcess>
<Order>
<AccountInternalId e-dtype="int">
<!-- THIS DOESN'T POINT TO ANY EXISTING NODE!! -->
<xsl:value-of select="ns:Request/ns:Response/ns:ResponseList/ns:Response/ns:ServiceOrder/ns:AccountInternalId"/>
</AccountInternalId>
<Key>
<OrderId e-dtype="numeric">
<!-- THIS DOESN'T POINT TO ANY EXISTING NODE!! -->
<xsl:value-of select="ns:Request/ns:Response/ns:ResponseList/ns:Response/ns:ServiceOrder/ns:OrderId"/>
</OrderId>
</Key>
</Order>
<xsl:apply-templates select="ns:Request/ns:Response/ns:ResponseList/ns:Response/ns:ServiceOrder"/>
</LogicalServiceOrderPreProcess>
</LogicalServiceOrder>
</RequestList>
</CustomerUdtRequest>
</Request>
</xsl:template>
<xsl:template match="ns:ServiceOrder">
<xsl:copy>
<xsl:copy-of select="ns:CreateWho"/>
<xsl:apply-templates select="ns:CreateDt | ns:WorkflowStartDt"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ns:CreateDt | ns:WorkflowStartDt">
<xsl:copy>
<xsl:copy-of select="#*"/>
<xsl:value-of select="concat('**', ., '**')"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
When applied to your input (minus the illegal opening comment), the following result is obtained:
<?xml version="1.0" encoding="UTF-8"?>
<Request>
<Header>
<OperatorName e-dtype="string">ws</OperatorName>
<ApplicationName e-dtype="string">ws</ApplicationName>
</Header>
<CustomerUdtRequest>
<RequestList e-dtype="list">
<LogicalServiceOrder>
<RequestId e-dtype="string">MyExistingOrder</RequestId>
<LogicalServiceOrderPreProcess>
<Order>
<AccountInternalId e-dtype="int"/>
<Key>
<OrderId e-dtype="numeric"/>
</Key>
</Order>
<ServiceOrder xmlns="fst" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<CreateWho e-dtype="string">vc</CreateWho>
<CreateDt e-dtype="dateTime">**2014-03-01 00:00:00**</CreateDt>
<WorkflowStartDt e-dtype="dateTime">**2014-04-01 00:00:00**</WorkflowStartDt>
</ServiceOrder>
</LogicalServiceOrderPreProcess>
</LogicalServiceOrder>
</RequestList>
</CustomerUdtRequest>
</Request>