I am pulling clob data from a JDBC server and the below is the sample format of the xml
1
<?xml version="1.0" encoding="utf-8"?>
<Sales_Posting>
<row>
<ORGANIZATION_ID>1</ORGANIZATION_ID>
<RTL_LOC_ID>269</RTL_LOC_ID>
<POSLOG_DATA><?xml version="1.0" encoding="UTF-8"?>
<POSLog xmlns="http://www.nrf-arts.org/IXRetail/namespace/"
xmlns:dtv="http://www.datavantagecorp.com/xstore/"
xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
xs:schemaLocation="http://www.nrf-arts.org/IXRetail/namespace/ POSLog.xsd" >
<Transaction xmlns:dtv="http://www.datavantagecorp.com/xstore/" CancelFlag="true" OfflineFlag="false" TrainingModeFlag="false" dtv:AppVersion="17.0.0.0.716 - 0.0.0 - 0.0" dtv:TransactionType="RETAIL_SALE" >
<dtv:OrganizationID><![CDATA[1]]></dtv:OrganizationID>
<RetailStoreID><![CDATA[269]]></RetailStoreID>
<WorkstationID><![CDATA[2]]></WorkstationID>
</Transaction>
</POSLog></POSLOG_DATA>
<CREATE_DATE>2019-07-17 20:57:56.536</CREATE_DATE>
</row>
<row>
<ORGANIZATION_ID>1</ORGANIZATION_ID>
<RTL_LOC_ID>269</RTL_LOC_ID>
<POSLOG_DATA><?xml version="1.0" encoding="UTF-8"?>
<POSLog xmlns="http://www.nrf-arts.org/IXRetail/namespace/"
xmlns:dtv="http://www.datavantagecorp.com/xstore/"
xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
xs:schemaLocation="http://www.nrf-arts.org/IXRetail/namespace/ POSLog.xsd" >
<Transaction xmlns:dtv="http://www.datavantagecorp.com/xstore/" CancelFlag="false" OfflineFlag="false" TrainingModeFlag="false" dtv:AppVersion="17.0.0.0.716 - 0.0.0 - 0.0" dtv:TransactionType="RETAIL_SALE" >
<dtv:OrganizationID><![CDATA[1]]></dtv:OrganizationID>
<RetailStoreID><![CDATA[269]]></RetailStoreID>
<WorkstationID><![CDATA[2]]></WorkstationID>
</Transaction>
</POSLog></POSLOG_DATA>
<CREATE_DATE>2019-07-18 06:20:38.014</CREATE_DATE>
</row>
</Sales_Posting>
I need to pull the xml inside the tag .
For a single record I am able to pull the data using the below code
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" indent="yes"/>
<xsl:template match="/">
<xsl:value-of select="/Sales_Posting/row/POSLOG_DATA"/>
</xsl:template>
</xsl:stylesheet>
But I require it for multiple records.
XSLT 1.0 is preferable. If the result is possible via multiple xslt mappings then that is also fine for me.
Expected Output is :-
2
<?xml version="1.0" encoding="utf-8"?>
<Sales_Posting>
<row>
<POSLog xmlns="http://www.nrf-arts.org/IXRetail/namespace/"
xmlns:dtv="http://www.datavantagecorp.com/xstore/"
xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
xs:schemaLocation="http://www.nrf-arts.org/IXRetail/namespace/ POSLog.xsd">
<Transaction CancelFlag="true"
OfflineFlag="false"
TrainingModeFlag="false"
dtv:AppVersion="17.0.0.0.716 - 0.0.0 - 0.0"
dtv:TransactionType="RETAIL_SALE">
<dtv:OrganizationID>1</dtv:OrganizationID>
<RetailStoreID>269</RetailStoreID>
<WorkstationID>2</WorkstationID>
</Transaction>
</POSLog>
</row>
<row>
<POSLog xmlns="http://www.nrf-arts.org/IXRetail/namespace/"
xmlns:dtv="http://www.datavantagecorp.com/xstore/"
xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
xs:schemaLocation="http://www.nrf-arts.org/IXRetail/namespace/ POSLog.xsd">
<Transaction CancelFlag="true"
OfflineFlag="false"
TrainingModeFlag="false"
dtv:AppVersion="17.0.0.0.716 - 0.0.0 - 0.0"
dtv:TransactionType="RETAIL_SALE">
<dtv:OrganizationID>1</dtv:OrganizationID>
<RetailStoreID>269</RetailStoreID>
<WorkstationID>2</WorkstationID>
</Transaction>
</POSLog>
</row>
</Sales_Posting>
I am sharing the image of source structure as well as the expected target structure. Kindly help.
Try:
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="/Sales_Posting">
<xsl:copy>
<xsl:for-each select="row">
<xsl:copy>
<xsl:value-of select="substring-after(POSLOG_DATA, '?>')" disable-output-escaping="yes"/>
</xsl:copy>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
The result must be saved to file before processed further. This is assuming your processor supports disable-output-escaping.
Related
I have an xml that looks like below.
<?xml version="1.0" encoding="UTF-8"?>
<Invoice xsi:schemaLocation="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2 http://docs.oasis-open.org/ubl/os-UBL-2.1/xsd/maindoc/UBL-Invoice-2.1.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2" xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns:ext="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2" xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">
<cac:InvoiceLine>
<cbc:ID></cbc:ID>
<cbc:LineExtensionAmount currencyID="EUR">93.46</cbc:LineExtensionAmount>
<cac:Item>
<cac:AdditionalItemProperty>
<cbc:Name>Total Hours</cbc:Name>
<cbc:Value>43</cbc:Value>
</cac:AdditionalItemProperty>
<cac:AdditionalItemProperty>
<cbc:Name>naamKandidaat</cbc:Name>
<cbc:Value>Kees Netelvrees</cbc:Value>
</cac:AdditionalItemProperty>
</cac:Item>
</cac:InvoiceLine>
<cac:InvoiceLine>
<cbc:ID></cbc:ID>
<cbc:LineExtensionAmount currencyID="EUR">2.77</cbc:LineExtensionAmount>
<cac:Item>
<cac:AdditionalItemProperty>
<cbc:Name>Total Hours</cbc:Name>
<cbc:Value>43</cbc:Value>
</cac:AdditionalItemProperty>
<cac:AdditionalItemProperty>
**<cbc:Name>naamKandidaat</cbc:Name>**
<cbc:Value>Jaap Aap</cbc:Value>
</cac:AdditionalItemProperty>
</cac:Item>
</cac:InvoiceLine>
<cac:InvoiceLine>
<cbc:ID></cbc:ID>
<cbc:LineExtensionAmount currencyID="EUR">100.00</cbc:LineExtensionAmount>
<cac:Item>
<cac:AdditionalItemProperty>
<cbc:Name>Total Hours</cbc:Name>
<cbc:Value>43</cbc:Value>
</cac:AdditionalItemProperty>
<cac:AdditionalItemProperty>
**<cbc:Name>naamKandidaat</cbc:Name>**
<cbc:Value>Jaap Aap</cbc:Value>
</cac:AdditionalItemProperty>
</cac:Item>
</cac:InvoiceLine>
</Invoice>
I need to group cac:InvoiceLine/cac:Item/cac:AdditionalItemProperty/cbc:Value where InvoiceLine/cac:Item/cac:AdditionalItemProperty/cbc:Name**=naamKandidaat**.
The purpose is to sum nodes within cac:InvoiceLine where cbc:Name is the same.
The problem is that I do not know how to create the key
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2" xmlns:ccts="urn:un:unece:uncefact:documentation:2" xmlns:qdt="urn:oasis:names:specification:ubl:schema:xsd:QualifiedDatatypes-2" xmlns:udt="urn:un:unece:uncefact:data:specification:UnqualifiedDataTypesSchemaModule:2" xmlns:default="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" exclude-result-prefixes="cac cbc ccts qdt udt default">
<xsl:output method="xml" encoding="utf-8" indent="yes"/>
<xsl:key name="PerAdditionalItemProperty" match="cac:InvoiceLine" use="cac:Item/cac:AdditionalItemProperty/cbc:Value"/>
<xsl:template match="/">
<PurchaseInvoices_version_1.0>
<xsl:for-each select="default:Invoice">
<PurchaseInvoice>
<xsl:for-each select="cac:InvoiceLine[generate-id(.)=generate-id(key('PerAdditionalItemProperty',cac:Item/cac:AdditionalItemProperty/cbc:Value)[1])]">
<xsl:for-each select="key('PerAdditionalItemProperty',cac:Item/cac:AdditionalItemProperty/cbc:Value)">
<xsl:if test="position()=1">
<Line>
<Item><xsl:value-of select="cac:Item/cac:AdditionalItemProperty/cbc:Value"/></Item>
<LineAmount><xsl:value-of select="format-number(sum(key('PerAdditionalItemProperty',cac:Item/cac:AdditionalItemProperty/cbc:Value)/cbc:LineExtensionAmount[number(.) = number(.)]),'#.##')"/></LineAmount>
</Line>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
</PurchaseInvoice>
</xsl:for-each>
</PurchaseInvoices_version_1.0>
</xsl:template>
</xsl:stylesheet>
The output that I expect is:
<?xml version="1.0" encoding="utf-8"?>
<PurchaseInvoices_version_1.0>
<PurchaseInvoice>
<Line>
<Item>Kees Netelvrees</Item>
<LineAmount>93.46</LineAmount>
</Line>
<Line>
<Item>Jaap Aap</Item>
<LineAmount>102.77</LineAmount>
</Line>
</PurchaseInvoice>
</PurchaseInvoices_version_1.0
You just need to put the conditions into the key expression:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
version="1.0">
<xsl:output indent="yes"/>
<xsl:key name="group" match="cac:InvoiceLine" use="cac:Item/cac:AdditionalItemProperty[cbc:Name = 'naamKandidaat']/cbc:Value"/>
<xsl:template match="cac:InvoiceLine[generate-id() = generate-id(key('group', cac:Item/cac:AdditionalItemProperty[cbc:Name = 'naamKandidaat']/cbc:Value)[1])]">
<Line>
<Item>
<xsl:value-of select="cac:Item/cac:AdditionalItemProperty[cbc:Name = 'naamKandidaat']/cbc:Value"/>
</Item>
<LineAmount>
<xsl:value-of select="sum(key('group', cac:Item/cac:AdditionalItemProperty[cbc:Name = 'naamKandidaat']/cbc:Value)/cbc:LineExtensionAmount)"/>
</LineAmount>
</Line>
</xsl:template>
<xsl:template match="cac:InvoiceLine[not(generate-id() = generate-id(key('group', cac:Item/cac:AdditionalItemProperty[cbc:Name = 'naamKandidaat']/cbc:Value)[1]))]"/>
<xsl:template match="/">
<PurchaseInvoices_version_1.0>
<PurchaseInvoice>
<xsl:apply-templates/>
</PurchaseInvoice>
</PurchaseInvoices_version_1.0>
</xsl:template>
</xsl:stylesheet>
I have a merged report data(data comes from two sources)as an input file and I needed to lookup a value based on a key. Currently my code is returning incorrectly looking up values. Since the size of the input data is expected to be large, I would like to use streaming for better performance.
Here is my input xml
Element Number'is the key to lookup. Xpath is 'Batch/Workers/Number`
Lookup Phone element based on Number' . Xpath isMergedOutput/Data/Row/Phone`
Sample Input
<?xml version="1.0" encoding="UTF-8"?>
<MergedOutput>
<Data>
<Row>
<Employee_Batch_Id>12567</Employee_Batch_Id>
<Phone>FirstEmp8013457896</Phone>
<Assignment_Id>5046150263</Assignment_Id>
</Row>
<Row>
<Employee_Batch_Id>12568</Employee_Batch_Id>
<Phone>SecondEmp7853457896</Phone>
<Assignment_Id>5046150263</Assignment_Id>
</Row>
</Data>
<Batch>
<Workers>
<Number>12567</Number>
<Contact>Work7864532890</Contact>
</Workers>
<Workers>
<Number>12568</Number>
<Contact>Work6782340167</Contact>
</Workers>
</Batch>
</MergedOutput>
Current XSLT3 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"
xmlns:map="http://www.w3.org/2005/xpath-functions/map"
exclude-result-prefixes="xs r1 r2 map"
version="3.0">
<xsl:output method="xml" indent="yes"/>
<xsl:mode streamable="yes" on-no-match="shallow-skip" use-accumulators="#all"/>
<xsl:accumulator name="FirstReportLookupValuePhone" as="xs:string" initial-value="''" streamable="yes">
<xsl:accumulator-rule match="Phone/text()" select="."/>
</xsl:accumulator>
<xsl:accumulator name="EmployeeIDLookup" as="map(xs:string,xs:string)" initial-value="map{}" streamable="yes">
<xsl:accumulator-rule match="Employee_Batch_Id/text()" select="map:put($value, string(.), accumulator-before('FirstReportLookupValuePhone'))"/>
</xsl:accumulator>
<xsl:template match="Batch">
<Workers>
<xsl:apply-templates select="Workers"/>
</Workers>
</xsl:template>
<xsl:template match="Workers">
<xsl:variable name="vWorkers" select="copy-of()"/>
<xsl:variable name="vMappedWorker" select="accumulator-after('EmployeeIDLookup')( normalize-space($vWorkers/Number))"/>
<Worker>
<WorkerID><xsl:value-of select="$vWorkers/Number"/></WorkerID>
<Work_Contact_Number><xsl:value-of select="$vWorkers/Contact"/></Work_Contact_Number>
<Home_Contact_Number><xsl:value-of select="$vMappedWorker"/></Home_Contact_Number>
</Worker>
</xsl:template>
</xsl:stylesheet>
Current output
<?xml version="1.0" encoding="UTF-8"?>
<Workers>
<Worker>
<WorkerID>12567</WorkerID>
<Work_Contact_Number>Work7864532890</Work_Contact_Number>
<Home_Contact_Number/> <!-- Value is empty, Expected value is FirstEmp8013457896 -->
</Worker>
<Worker>
<WorkerID>12568</WorkerID>
<Work_Contact_Number>Work6782340167</Work_Contact_Number>
<Home_Contact_Number>FirstEmp8013457896</Home_Contact_Number> <!-- Incorrect Value, Expected value is SecondEmp7853457896 -->
</Worker>
</Workers>
Expected Output
<?xml version="1.0" encoding="UTF-8"?>
<Workers>
<Worker>
<WorkerID>12567</WorkerID>
<Work_Contact_Number>Work7864532890</Work_Contact_Number>
<Home_Contact_Number>FirstEmp8013457896</Home_Contact_Number>
</Worker>
<Worker>
<WorkerID>12568</WorkerID>
<Work_Contact_Number>Work6782340167</Work_Contact_Number>
<Home_Contact_Number>SecondEmp7853457896</Home_Contact_Number>
</Worker>
</Workers>
Please could someone help me figure out how could i get the desired output?
The problem is that the accumulator matching Employee_Batch_ID tries to use the accumulator value for Phone; but because the Employee_Batch_ID appears before the Phone element, the Phone accumulator value isn't available yet.
I think you have to reverse the logic: when you encounter an Employee_Batch_ID/text(), save the ID value as a string in accumulator A; when you encounter a Phone/text(), add an ID=phone entry to a map held in Accumulator B.
I need to group some of the fields into a segment when the segment does not appear.
I am able to add the segment by checking if the segment already exists.
XML
<ns1:MT_SalesOrder xmlns:ns1="urn:salesorder">
<Reason/>
<OrderId/>
<Invoice>
<CreatedTimestamp>2019-07-24T14:37:29.573</CreatedTimestamp>
<PublishCount>1</PublishCount>
<Process/>
<FailedAmount/>
<InvoiceLine>
<Address/>
<Total>-270.0</Total>
</InvoiceLine>
</Invoice>
<Info/>
<Comments/>
<Status/>
<Taxes/>
<Due>0.0</Due>
<OrderTotal>5.0</OrderTotal>
<messageKey>122345</messageKey>
<message>99999</message>
<errors>11111</errors>
<exceptions>222222</exceptions>
</ns1:MT_SalesOrder>
XSLT
<?xml version="1.0" encoding="UTF-8"?>
<ns0:stylesheet version="1.0" xmlns:ns0="http://www.w3.org/1999/XSL/Transform" xmlns:ns1="urn:salesorder">
<ns0:output omit-xml-declaration="yes" indent="yes"/>
<ns0:strip-space elements="*"/>
<ns0:template match="node()|#*">
<ns0:copy>
<ns0:apply-templates select="node()|#*"/>
</ns0:copy>
</ns0:template>
<ns0:template match="/ns1:MT_SalesOrder[not(data)]">
<ns0:copy>
<ns0:apply-templates select="#*"/>
<data>
<ns0:apply-templates select="node()"/>
</data>
</ns0:copy>
</ns0:template>
</ns0:stylesheet>
I am expecting the below structure, data to be added before messageKey Field.
<ns1:MT_SalesOrder xmlns:ns1="urn:salesorder">
<data> <---------------------------------------------
<Reason/>
<OrderId/>
<Invoice>
<CreatedTimestamp>2019-07-24T14:37:29.573</CreatedTimestamp>
<PublishCount>1</PublishCount>
<Process/>
<FailedAmount/>
<InvoiceLine>
<Address/>
<Total>-270.0</Total>
</InvoiceLine>
</Invoice>
<Info/>
<Comments/>
<Status/>
<Taxes/>
<Due>0.0</Due>
<OrderTotal>5.0</OrderTotal>
</data> <-------------------------------------------------
<messageKey>122345</messageKey>
<message>99999</message>
<errors>11111</errors>
<exceptions>222222</exceptions>
</ns1:MT_SalesOrder>
But I am getting the data segment added to the whole XML.
<ns1:MT_SalesOrder xmlns:ns1="urn:salesorder">
<data>
<Reason/>
<OrderId/>
<Invoice>
<CreatedTimestamp>2019-07-24T14:37:29.573</CreatedTimestamp>
<PublishCount>1</PublishCount>
<Process/>
<FailedAmount/>
<InvoiceLine>
<Address/>
<Total>-270.0</Total>
</InvoiceLine>
</Invoice>
<Info/>
<Comments/>
<Status/>
<Taxes/>
<Due>0.0</Due>
<OrderTotal>5.0</OrderTotal>
<messageKey>122345</messageKey>
<message>99999</message>
<errors>11111</errors>
<exceptions>222222</exceptions>
</data>
</ns1:MT_SalesOrder>
I am not able to copy the part of the XML and group them, the field messageKey is the identifier to split the XML and add in data segment. Any leads will be helpful. Thank you!
If you know in advance the names of all elements in the two groups, then the best way is to list them explicitly:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns1="urn:salesorder">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="ns1:MT_SalesOrder">
<xsl:copy>
<data>
<xsl:copy-of select="Reason | OrderId | Invoice | Info | Comments | Status | Taxes | Due | OrderTotal"/>
</data>
<xsl:copy-of select="messageKey | message | errors | exceptions"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Otherwise you can use messageKey as the "split point":
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns1="urn:salesorder">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="ns1:MT_SalesOrder">
<xsl:copy>
<data>
<xsl:copy-of select="messageKey/preceding-sibling::*"/>
</data>
<xsl:copy-of select="messageKey | messageKey/following-sibling::*"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
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>
I am trying to transform XML into another XML file but unsuccessfully changing a flat element into an expanded element.
The output should be identical except DateOfBirth should be changed to:
<DateOfBirth>
<FullDate xmlns="cds_dt">1966-02-11</FullDate>
</DateOfBirth>
Here are the input files I am using:
Input
*****
<?xml version="1.0" encoding="utf-8"?>
<RootRec xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="cds">
<MyRecord>
<Demographics>
<Names>
<LegalName namePurpose="L" xmlns="cds_dt">
<FirstName>
<Part>Jason</Part>
<PartType>GIV</PartType>
</FirstName>
<LastName>
<Part>Smith</Part>
<PartType>FAMC</PartType>
</LastName>
<OtherName>
<Part>Lauren</Part>
<PartType>GIV</PartType>
</OtherName>
</LegalName>
</Names>
<DateOfBirth>1966-02-11</DateOfBirth>
<Demographics>
<MyRecord>
</RootRec>
XSL file
********
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<!--Identity Template. This will copy everything as-is.-->
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<!--expand "DateOfBirth" element to /DateOfBirth/FullDate element.-->
<xsl:template match="RootRec/MyRecord/Demographics/DateOfBirth">
<DateOfBirth>
<FullDate><xsl:value-of select="DateOfBirth"/></FullDate>
</DateOfBirth>
</xsl:template>
</xsl:stylesheet>
This transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:x="cds">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="x:DateOfBirth/text()">
<xsl:element name="FullDate" xmlns="cds_dt"><xsl:value-of select="."/></xsl:element>
</xsl:template>
</xsl:stylesheet>
when applied on the provided (corrected to be made wellformed) XML document:
<RootRec
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="cds">
<MyRecord>
<Demographics>
<Names>
<LegalName namePurpose="L" xmlns="cds_dt">
<FirstName>
<Part>Jason</Part>
<PartType>GIV</PartType>
</FirstName>
<LastName>
<Part>Smith</Part>
<PartType>FAMC</PartType>
</LastName>
<OtherName>
<Part>Lauren</Part>
<PartType>GIV</PartType>
</OtherName>
</LegalName>
</Names>
<DateOfBirth>1966-02-11</DateOfBirth>
</Demographics>
</MyRecord>
</RootRec>
produces the wanted, correct result:
<RootRec xmlns="cds" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<MyRecord>
<Demographics>
<Names>
<LegalName xmlns="cds_dt" namePurpose="L">
<FirstName>
<Part>Jason</Part>
<PartType>GIV</PartType>
</FirstName>
<LastName>
<Part>Smith</Part>
<PartType>FAMC</PartType>
</LastName>
<OtherName>
<Part>Lauren</Part>
<PartType>GIV</PartType>
</OtherName>
</LegalName>
</Names>
<DateOfBirth>
<FullDate xmlns="cds_dt">1966-02-11</FullDate>
</DateOfBirth>
</Demographics>
</MyRecord>
</RootRec>
Explanation: Overriding the identity rule.
It should be
<FullDate><xsl:value-of select="."/></FullDate>
since you're already selecting the DateOfBirth in the match=""
You also have missing / in the three closing tags before the document end, and your namespace names are invalid because they must be absolute URIs.
Good luck.