xslt, group by node with specific value (multiple nodes with same name in each line) (key problem) - xslt

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>

Related

Using XSLT to output only the id and the value of the “wert” Element?

Given the XML code:
<?xml version="1.0" encoding="utf-8"?>
<autoverleih>
<kunden>
<kunde id="p1">
<name nachname="Mustermann" vorname="Mario"/>
<versicherung name="super1" kasko="true"/>
</kunde>
<kunde id="p4">
<name nachname="Gans" vorname="Maria"/>
<versicherung name="die-beste" kasko="false"/>
</kunde>
<kunde id="p54">
<name nachname="Gans" vorname="Gustav"/>
<versicherung name="super1" kasko="false"/>
</kunde>
</kunden>
<ausleihen>
<vertrag kunde="p1" wert="1521.07" datum="2014-07-02" bezahlt="true"/>
<vertrag kunde="p4" wert="397.96" datum="2014-07-12" bezahlt="false"/>
<vertrag kunde="p1" wert="51.23" datum="2014-06-13" bezahlt="true"/>
<vertrag kunde="p54" wert="127.12" datum="2014-08-01" bezahlt="false"/>
</ausleihen>
</autoverleih>
And the following XSLT:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform". version="2.0">
<xsl:template match=”autoverleih">
<xsl:value-of select="./kunden/kunde/#id”>
</xsl:template>
<xsl:template match=”vertrag”>
<xsl:value-of select=”../kunde”/>
<xsl:value-of select=”./wert”/>
</xsl:template>
</xsl:stylesheet>
I need to change this code so that for each kunde it only outputs its Id and the wert attribute.
If you want to reference vertrag from kunde I think you can use a key:
<?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="#all"
version="3.0">
<xsl:output method="text"/>
<xsl:key name="vertrag-des-kunden" match="vertrag" use="#kunde"/>
<xsl:template match="/">
<xsl:value-of
select="//kunde/#id/concat(., ': ', string-join(key('vertrag-des-kunden', .)/#wert, ', '))"
separator="
"/>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/a9HjZU

How to create 1 group to sum 4 elements with xslt

I am trying to use muenchian to do a group/sum, but I can't make it work.
Any help available?! :)
XML I have:
<RLA760910>
<G_L_By_Object_Account___Localization_S10>
<Zsz_ObjectAcctSub_OSBOW_ID3>401100.900</Zsz_ObjectAcctSub_OSBOW_ID3>
<SumBegBalance>-20</SumBegBalance>
<SumDebitPeriod>10</SumDebitPeriod>
<SumCreditPeriod>-5</SumCreditPeriod>
<SumEndBalance>-15</SumEndBalance>
</G_L_By_Object_Account___Localization_S10>
<G_L_By_Object_Account___Localization_S10>
<Zsz_ObjectAcctSub_OSBOW_ID3>401100.900</Zsz_ObjectAcctSub_OSBOW_ID3>
<SumBegBalance>100</SumBegBalance>
<SumDebitPeriod>10</SumDebitPeriod>
<SumCreditPeriod>-5</SumCreditPeriod>
<SumEndBalance>105</SumEndBalance>
</G_L_By_Object_Account___Localization_S10>
<Zsz_ObjectAcctSub_OSBOW_ID3>411100.900</Zsz_ObjectAcctSub_OSBOW_ID3>
<SumBegBalance>-30</SumBegBalance>
<SumDebitPeriod>5</SumDebitPeriod>
<SumCreditPeriod>-10</SumCreditPeriod>
<SumEndBalance>-35</SumEndBalance>
</G_L_By_Object_Account___Localization_S10>
<Zsz_ObjectAcctSub_OSBOW_ID3>451100.900</Zsz_ObjectAcctSub_OSBOW_ID3>
<SumBegBalance>80</SumBegBalance>
<SumDebitPeriod>20</SumDebitPeriod>
<SumCreditPeriod>-10</SumCreditPeriod>
<SumEndBalance>90</SumEndBalance>
</G_L_By_Object_Account___Localization_S10>
</RLA760910>
I've so far:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0"
<xsl:key name="AcctSub"
match="/RLA760910/G_L_By_Object_Account___Localization_S10"
use="#Zsz_ObjectAcctSub_OSBOW_ID3" />
<xsl:template match="Zsz_ObjectAcctSub_OSBOW_ID3">
<result>
<!-- Match the first acct element for a specific group -->
<xsl:apply-templates select="/RLA760910/G_L_By_Object_Account___Localization_S10/[generate-id() = generate-id(key('AcctSub', #Zsz_ObjectAcctSub_OSBOW_ID3)[1])]" />
</result>
</xsl:template>
<xsl:template match="/RLA760910/G_L_By_Object_Account___Localization_S10">
<total type="{#Zsz_ObjectAcctSub_OSBOW_ID3}">
<!-- Sum all the elements from the #type group -->
<xsl:value-of select="sum(key('AcctSub', #Zsz_ObjectAcctSub_OSBOW_ID3)/#Zsz_ObjectAcctSub_OSBOW_ID3)" />
</total>
</xsl:template>
</xsl:stylesheet>
Expected result will sum
SumBegBalance, SumDebitPeriod, SumCreditPeriod, SumEndBalance Group BY Zsz_ObjectAcctSub_OSBOW_ID3
Use the following script:
<?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" omit-xml-declaration="yes" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:key name="AcctSub"
match="G_L_By_Object_Account___Localization_S10"
use="Zsz_ObjectAcctSub_OSBOW_ID3"/>
<xsl:template match="RLA760910">
<xsl:copy>
<xsl:for-each select="*[generate-id()=generate-id(
key('AcctSub', Zsz_ObjectAcctSub_OSBOW_ID3)[1])]">
<result>
<xsl:variable name="Objects" select="key('AcctSub',
Zsz_ObjectAcctSub_OSBOW_ID3)"/>
<Zsz_ObjectAcctSub_OSBOW_ID3>
<xsl:value-of select="Zsz_ObjectAcctSub_OSBOW_ID3"/>
</Zsz_ObjectAcctSub_OSBOW_ID3>
<SumBegBalance>
<xsl:value-of select="sum($Objects/SumBegBalance)"/>
</SumBegBalance>
<SumDebitPeriod>
<xsl:value-of select="sum($Objects/SumDebitPeriod)"/>
</SumDebitPeriod>
<SumCreditPeriod>
<xsl:value-of select="sum($Objects/SumCreditPeriod)"/>
</SumCreditPeriod>
<SumEndBalance>
<xsl:value-of select="sum($Objects/SumEndBalance)"/>
</SumEndBalance>
</result>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
A few notes:
Zsz_ObjectAcctSub_OSBOW_ID3 is not an atribute but an element, so #
is not needed.
As the name of the root tag I used the same name as in your input.
Each result output tag contains Zsz_ObjectAcctSub_OSBOW_ID3 tag
(the grouping key) and sums of your 4 tags (within the group).
Try this as your starting point:
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:key name="grp" match="G_L_By_Object_Account___Localization_S10" use="Zsz_ObjectAcctSub_OSBOW_ID3" />
<xsl:template match="/RLA760910">
<result>
<xsl:for-each select="G_L_By_Object_Account___Localization_S10[generate-id() = generate-id(key('grp', Zsz_ObjectAcctSub_OSBOW_ID3)[1])]" >
<group type="{Zsz_ObjectAcctSub_OSBOW_ID3}">
<total-of-begbalance>
<xsl:value-of select="sum(key('grp', Zsz_ObjectAcctSub_OSBOW_ID3)/SumBegBalance)"/>
</total-of-begbalance>
<!-- add more totals here-->
</group>
</xsl:for-each>
</result>
</xsl:template>
</xsl:stylesheet>
When this is applied to the following well-formed example input:
XML
<RLA760910>
<G_L_By_Object_Account___Localization_S10>
<Zsz_ObjectAcctSub_OSBOW_ID3>401100.900</Zsz_ObjectAcctSub_OSBOW_ID3>
<SumBegBalance>-20</SumBegBalance>
<SumDebitPeriod>10</SumDebitPeriod>
<SumCreditPeriod>-5</SumCreditPeriod>
<SumEndBalance>-15</SumEndBalance>
</G_L_By_Object_Account___Localization_S10>
<G_L_By_Object_Account___Localization_S10>
<Zsz_ObjectAcctSub_OSBOW_ID3>401100.900</Zsz_ObjectAcctSub_OSBOW_ID3>
<SumBegBalance>100</SumBegBalance>
<SumDebitPeriod>10</SumDebitPeriod>
<SumCreditPeriod>-5</SumCreditPeriod>
<SumEndBalance>105</SumEndBalance>
</G_L_By_Object_Account___Localization_S10>
<G_L_By_Object_Account___Localization_S10>
<Zsz_ObjectAcctSub_OSBOW_ID3>411100.900</Zsz_ObjectAcctSub_OSBOW_ID3>
<SumBegBalance>-30</SumBegBalance>
<SumDebitPeriod>5</SumDebitPeriod>
<SumCreditPeriod>-10</SumCreditPeriod>
<SumEndBalance>-35</SumEndBalance>
</G_L_By_Object_Account___Localization_S10>
<G_L_By_Object_Account___Localization_S10>
<Zsz_ObjectAcctSub_OSBOW_ID3>451100.900</Zsz_ObjectAcctSub_OSBOW_ID3>
<SumBegBalance>80</SumBegBalance>
<SumDebitPeriod>20</SumDebitPeriod>
<SumCreditPeriod>-10</SumCreditPeriod>
<SumEndBalance>90</SumEndBalance>
</G_L_By_Object_Account___Localization_S10>
</RLA760910>
the result will be:
<?xml version="1.0" encoding="utf-8"?>
<result>
<group type="401100.900">
<total-of-begbalance>80</total-of-begbalance>
</group>
<group type="411100.900">
<total-of-begbalance>-30</total-of-begbalance>
</group>
<group type="451100.900">
<total-of-begbalance>80</total-of-begbalance>
</group>
</result>
Note that your expressions using #Zsz_ObjectAcctSub_OSBOW_ID3 fail because Zsz_ObjectAcctSub_OSBOW_ID3 is an element, not an attribute.

Removing an XML element based on the value of other element

I have to achieve below.
if <m_control>/<initiator_id> is Dummy then the xml element, <note>/<reason> should be removed.Below is the hirarchy of the note element.
<o:m_content/o:application/o:product/o:client_specific_illustration/o:note>
Below is the sample xml:
<?xml version="1.0"?>
<message xmlns="http://www.origoservices.com" xmlns:ns2="http://www.w3.org/2000/09/xmldsig#">
<m_control>
<expected_response_type>synchronous</expected_response_type>
<initiator_id>Dummy</initiator_id>
<user_id>Dummy</user_id>
<responder_id>Responder</responder_id>
</m_control>
<m_content>
<b_control>
<message_version_number>3.7</message_version_number>
<submission_date>2014-04-14</submission_date>
</b_control>
<intermediary type="Test">
<rdr_basis_of_sale>
<advised_category>Independent</advised_category>
</rdr_basis_of_sale>
</intermediary>
<application>
<address id="ADPC2">
<postcode>AB24 3DB</postcode>
</address>
<address id="ADPC1">
<postcode>B14 7JG</postcode>
</address>
<personal_client id="PC1">
<title>Mr</title>
<forenames>Test</forenames>
<surname>FLtwelve</surname>
<sex>Male</sex>
<marital_status>Married</marital_status>
<date_of_birth>1950-10-16</date_of_birth>
<employment_contract>
<occupation code="AAB00021">Actuary</occupation>
<full_time_ind>No</full_time_ind>
</employment_contract>
<smoker_ind>No</smoker_ind>
<residential_status>In Own Home - With Someone Else</residential_status>
<home_address address_id="ADPC1"/>
<enhanced_underwriting>
<medical_conditions/>
</enhanced_underwriting>
<tpsdata>
<postcode xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">test</postcode>
</tpsdata>
</personal_client>
<personal_client id="PC2">
<employment_contract>
<occupation code="WAB02558">Wig Maker</occupation>
<full_time_ind>Yes</full_time_ind>
</employment_contract>
<smoker_ind>Yes</smoker_ind>
<residential_status>In Own Home - Alone</residential_status>
<home_address address_id="ADPC2"/>
<enhanced_underwriting>
<medical_conditions/>
<lifestyle>
<height units="Centimetre">180</height>
<weight units="Kilogram">70</weight>
<waist units="Centimetre">81</waist>
<units_of_alcohol_per_week>1</units_of_alcohol_per_week>
<smoking_details>
<regular_smoker_ind>Yes</regular_smoker_ind>
<current_smoking>
<number_of_cigarettes_per_day>4</number_of_cigarettes_per_day>
<number_of_cigars_per_day>0</number_of_cigars_per_day>
<rolling_tobacco_per_week units="Gram">0</rolling_tobacco_per_week>
<pipe_tobacco_per_week units="Gram">0</pipe_tobacco_per_week>
<start_date>1985-09</start_date>
</current_smoking>
</smoking_details>
</lifestyle>
</enhanced_underwriting>
<tpsdata>
<postcode xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">AB24 3DB</postcode>
</tpsdata>
</personal_client>
<product type="Compulsory Purchase Annuity" product_code="CPA">
<open_market_option_ind>Yes</open_market_option_ind>
<annuity type="Non Protected Rights">
<annuitant sequence_number="1" personal_client_id="PC1"/>
<with_profit_ind>No</with_profit_ind>
<contribution legislation_applicable="Post 1997">
<amount currency="GBP">391586</amount>
<source_details>
<product_type>Occupational Scheme - Defined Contribution</product_type>
<product_provider_name>Other</product_provider_name>
<transfer_ind>No</transfer_ind>
</source_details>
<adviser_charges_applicable>
<adviser_charge_applicable adviser_charge_id="ac1"/>
</adviser_charges_applicable>
</contribution>
<payment_frequency>Annually</payment_frequency>
<payment_timing_code>In Advance</payment_timing_code>
<escalation>
<change_index>Level</change_index>
<lpi_lag_basis>Statutory</lpi_lag_basis>
<proportionate_escalation_ind>No</proportionate_escalation_ind>
</escalation>
<payment_period>
<start_basis>Specified Date</start_basis>
<start_date>2014-04-14</start_date>
</payment_period>
<guaranteed_period>
<years>5</years>
</guaranteed_period>
<commuted_ind>No</commuted_ind>
<with_proportion_ind>No</with_proportion_ind>
<reversionary_annuity type="Spouse" legislation_applicable="Post 1997">
<annuitant personal_client_id="PC2"/>
<number_of_dependants>1</number_of_dependants>
<fraction_of_original_payment>
<numerator>10</numerator>
<denominator>10</denominator>
</fraction_of_original_payment>
<payment_period>
<start_basis>Next Due Date</start_basis>
</payment_period>
<overlap_ind>No</overlap_ind>
<spouse_remarriage_cease_ind>Yes</spouse_remarriage_cease_ind>
</reversionary_annuity>
</annuity>
<adviser_charges>
<adviser_charge id="ac1">
<type>Adviser</type>
<amount currency="GBP">7831.72</amount>
<facilitated_from>Annuity In Payment</facilitated_from>
<facilitated_before_product_investment_ind>Yes</facilitated_before_product_investment_ind>
<payment_frequency>Single</payment_frequency>
<reason>Initial</reason>
</adviser_charge>
</adviser_charges>
<illustration_basis>
<annuity_calculation_required>Payment</annuity_calculation_required>
</illustration_basis>
<client_specific_illustration>
<expiry_date>2014-04-28</expiry_date>
<note>
<reason>reason for failure is specified over here</reason>
</note>
<pension_annuity type="Non Protected Rights">
<total_amount currency="GBP">18539.33</total_amount>
<reversionary_annuity>
<total_amount currency="GBP">18539.33</total_amount>
</reversionary_annuity>
</pension_annuity>
<adviser_charges>
<adviser_charge>
<adviser_charge_requested adviser_charge_id="ac1"/>
<type>Adviser</type>
<amount currency="GBP">7831.72</amount>
<facilitated_from>Annuity In Payment</facilitated_from>
<facilitated_before_product_investment_ind>Yes</facilitated_before_product_investment_ind>
<payment_frequency>Single</payment_frequency>
<reason>Initial</reason>
</adviser_charge>
</adviser_charges>
<tpsdata>
<guaranteed_quote>Yes</guaranteed_quote>
</tpsdata>
</client_specific_illustration>
</product>
<document_out type="Client Specific Illustration">
<print_requirements>
<distribution_method>Web Hosted</distribution_method>
<web_host_format>PDF</web_host_format>
</print_requirements>
</document_out>
</application>
</m_content>
</message>
Below is the xslt that I have tried, but I am not getting the expected output as the note/reason element is not getting removed.
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:o="http://www.origoservices.com" xmlns:dp="http://www.datapower.com/extensions" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:date="http://exslt.org/dates-and-times" version="1.0" extension-element-prefixes="dp" exclude-result-prefixes="fn date">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="o:m_content/o:application/o:product/o:client_specific_illustration/o:note[../../../../../o:m_control/o:initiator_id='TEX']">
</xsl:template>
</xsl:stylesheet>
Could anyone please let me know, where am I comiting mistake?
Regards.
Just have a variable to store the initiator_id. As below:
<xsl:variable name="test" select="o:message/o:m_control/o:initiator_id"/>
Then, test the note node
<xsl:template match="o:note[parent::o:client_specific_illustration]">
<xsl:choose>
<xsl:when test="$test='Dummy'"></xsl:when>
<xsl:otherwise>
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
The complete stylesheet therefore is:
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:o="http://www.origoservices.com" xmlns:dp="http://www.datapower.com/extensions"
xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:date="http://exslt.org/dates-and-times"
version="1.0" extension-element-prefixes="dp" exclude-result-prefixes="fn date">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:output method="xml" indent="yes"/>
<xsl:variable name="test" select="o:message/o:m_control/o:initiator_id"/>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="o:note[parent::o:client_specific_illustration]">
<xsl:choose>
<xsl:when test="$test='Dummy'"></xsl:when>
<xsl:otherwise>
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
as an alternative, you can just use
<xsl:template match="o:m_content[preceding-sibling::o:m_control/o:initiator_id='Dummy']/o:application/o:product/o:client_specific_illustration/o:note"/>

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>

XSLT: How to expand child element to have extra parent element

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.