Removing an XML element based on the value of other element - xslt

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"/>

Related

I tried to remove specific element if its output is empty in XSLT

I am trying to remove Error Description element if it contains empty value using xslt. i tried lot of options but it does not work.
For example if inside Acknowledgement all the element get null then output get empty acknowledgement so I want remove acknowledgement element empty tag.
below is xml and xslt
<?xml version="1.0" encoding="UTF-8" ?>
<updateDocumentStatusResponse xmlns="http://xmlns.be/CommgrService_Message/v001">
<Acknowledgement>
<Result>SUCCESS</Result>
<ErrorCode>ErrorCode1375</ErrorCode>
<ErrorDescription></ErrorDescription>
</Acknowledgement>
</updateDocumentStatusResponse>
XSLT :
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:ns1="http://xmlns.be/CSM/v001" xmlns:mhdr="http://www.oracle.com/XSL/Transform/java/oracle.tip.mediator.service.common.functions.MediatorExtnFunction" xmlns:oraext="http://www.oracle.com/XSL/Transform/java/oracle.tip.pc.services.functions.ExtFunc" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xp20="http://www.oracle.com/XSL/Transform/java/oracle.tip.pc.services.functions.Xpath20" xmlns:xref="http://www.oracle.com/XSL/Transform/java/oracle.tip.xref.xpath.XRefXPathFunctions" xmlns:socket="http://www.oracle.com/XSL/Transform/java/oracle.tip.adapter.socket.ProtocolTranslator" xmlns:oracle-xsl-mapper="http://www.oracle.com/xsl/mapper/schemas" xmlns:dvm="http://www.oracle.com/XSL/Transform/java/oracle.tip.dvm.LookupValue" xmlns:oraxsl="http://www.oracle.com/XSL/Transform/java" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns0="http://xmlns.be/CommgrService_Message/v001" exclude-result-prefixes=" xsd oracle-xsl-mapper xsi xsl ns1 ns0 mhdr oraext xp20 xref socket dvm oraxsl"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
<oracle-xsl-mapper:schema>
<oracle-xsl-mapper:mapSources>
<oracle-xsl-mapper:source type="WSDL">
<oracle-xsl-mapper:schema location="../WSDLs/CommgrService_v001.wsdl"/>
<oracle-xsl-mapper:rootElement name="updateDocumentStatusResponse" namespace="http://xmlns.be/CommgrService_Message/v001"/>
</oracle-xsl-mapper:source>
</oracle-xsl-mapper:mapSources>
</oracle-xsl-mapper:schema>
<!--User Editing allowed BELOW this line - DO NOT DELETE THIS LINE-->
<xsl:template match="/">
<ns1:Output>
<ns1:CommunicationResponse>
<ns1:Acknowledgement>
<ns1:Result>
<xsl:value-of select="/ns0:updateDocumentStatusResponse/ns0:Acknowledgement/ns0:Result"/>
</ns1:Result>
<ns1:ErrorCode>
<xsl:value-of select="/ns0:updateDocumentStatusResponse/ns0:Acknowledgement/ns0:ErrorCode"/>
</ns1:ErrorCode>
<ns1:ErrorDescription>
<xsl:value-of select="/ns0:updateDocumentStatusResponse/ns0:Acknowledgement/ns0:ErrorDescription"/>
</ns1:ErrorDescription>
</ns1:Acknowledgement>
</ns1:CommunicationResponse>
</ns1:Output>
</xsl:template>
</xsl:stylesheet>
how can i achieve this?
I think this can be done if you're not thinking something big:
<xsl:if test="normalize-space(/ns0:updateDocumentStatusResponse/ns0:Acknowledgement/ns0:ErrorDescription) != ''">
<ns1:ErrorDescription>
<xsl:value-of select="/ns0:updateDocumentStatusResponse/ns0:Acknowledgement/ns0:ErrorDescription"/>
</ns1:ErrorDescription>
</xsl:if>
Edit:
One way to achieve this using extension function like exsl:node-set or msxsl:node-set to be able to further process a result tree fragment created in another template:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:ns1="http://xmlns.be/CSM/v001" xmlns:mhdr="http://www.oracle.com/XSL/Transform/java/oracle.tip.mediator.service.common.functions.MediatorExtnFunction" xmlns:oraext="http://www.oracle.com/XSL/Transform/java/oracle.tip.pc.services.functions.ExtFunc" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xp20="http://www.oracle.com/XSL/Transform/java/oracle.tip.pc.services.functions.Xpath20" xmlns:xref="http://www.oracle.com/XSL/Transform/java/oracle.tip.xref.xpath.XRefXPathFunctions" xmlns:socket="http://www.oracle.com/XSL/Transform/java/oracle.tip.adapter.socket.ProtocolTranslator" xmlns:oracle-xsl-mapper="http://www.oracle.com/xsl/mapper/schemas" xmlns:dvm="http://www.oracle.com/XSL/Transform/java/oracle.tip.dvm.LookupValue" xmlns:oraxsl="http://www.oracle.com/XSL/Transform/java" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns0="http://xmlns.be/CommgrService_Message/v001" exclude-result-prefixes=" xsd oracle-xsl-mapper xsi xsl ns1 ns0 mhdr oraext xp20 xref socket dvm oraxsl"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
<oracle-xsl-mapper:schema>
<oracle-xsl-mapper:mapSources>
<oracle-xsl-mapper:source type="WSDL">
<oracle-xsl-mapper:schema location="../WSDLs/CommgrService_v001.wsdl" />
<oracle-xsl-mapper:rootElement name="updateDocumentStatusResponse" namespace="http://xmlns.be/CommgrService_Message/v001" />
</oracle-xsl-mapper:source>
</oracle-xsl-mapper:mapSources>
</oracle-xsl-mapper:schema>
<!--User Editing allowed BELOW this line - DO NOT DELETE THIS LINE -->
<xsl:template match="/">
<xsl:variable name="result">
<ns1:Output>
<ns1:CommunicationResponse>
<ns1:Acknowledgement>
<ns1:Result>
<xsl:value-of select="/ns0:updateDocumentStatusResponse/ns0:Acknowledgement/ns0:Result" />
</ns1:Result>
<ns1:ErrorCode>
<xsl:value-of select="/ns0:updateDocumentStatusResponse/ns0:Acknowledgement/ns0:ErrorCode" />
</ns1:ErrorCode>
<ns1:ErrorDescription>
<xsl:value-of select="/ns0:updateDocumentStatusResponse/ns0:Acknowledgement/ns0:ErrorDescription" />
</ns1:ErrorDescription>
</ns1:Acknowledgement>
</ns1:CommunicationResponse>
</ns1:Output>
</xsl:variable>
<xsl:apply-templates select="exsl:node-set($result)/*" mode="step2" />
</xsl:template>
<xsl:template match="*[not(normalize-space())]" mode="step2" />
<xsl:template match="#* | node()" mode="step2">
<xsl:copy>
<xsl:apply-templates select="#* | node()" mode="step2" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
http://xsltransform.net/93wkLHW
If you take a top-down aproach with literal result elements you are always going to get that element in the output. Your only choice then is to chain two transformations or use a two pass transformation.
The XPath expression to know whether the current node is empty (true) or not (false) is:
"not(node())"
For example, this input document
<?xml version="1.0" encoding="UTF-8" ?>
<updateDocumentStatusResponse xmlns="http://xmlns.be/CommgrService_Message/v001">
<Acknowledgement>
<Result>SUCCESS</Result>
<ErrorCode>ErrorCode1375</ErrorCode>
<ErrorDescription></ErrorDescription>
</Acknowledgement>
</updateDocumentStatusResponse>
With this transformation
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements ="*"/>
<xsl:output indent="yes"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[not(node())]"/>
</xsl:stylesheet>
Output
<updateDocumentStatusResponse xmlns="http://xmlns.be/CommgrService_Message/v001">
<Acknowledgement>
<Result>SUCCESS</Result>
<ErrorCode>ErrorCode1375</ErrorCode>
</Acknowledgement>
</updateDocumentStatusResponse>
Edit
The previus stylesheet is general. If you want to target specific elements, you need to match those elements with the pattern in the template. Example:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements ="*"/>
<xsl:output indent="yes"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ErrorDescription[not(node())]"/>
</xsl:stylesheet>

Attempting to remove element and reorder elements in resulting document

I have the following XML and XSLT.
I am attempting to exclude the NotUsed2 element from the resulting document.
I need to reorder the resulting so that AutoTypesetInfo follows NotUsed3.
XML:
<?xml version="1.0" encoding="ISO-8859-1" standalone="no" ?>
<Plan xmlns="http://www.ccieurope.com/xmlns/CCIPlanner">
<Header>
<Update>0</Update>
<NewsPaper>Pub1</NewsPaper>
<Date>080818</Date>
<Zone>MAIN</Zone>
<Edition>1st</Edition>
<Pages>26</Pages>
<Section>A B C </Section>
<Number>08082018</Number>
<Format>
<Height>21.70i</Height>
<Width>9.87i</Width>
</Format>
<PrintingInfo/>
<Version/>
<Config/>
<Default/>
<FileFormat>2.0</FileFormat>
<IssueName/>
</Header>
<Page>
<PhysicalBook>A</PhysicalBook>
<BookPageNumber>1</BookPageNumber>
<Desk>A</Desk>
<SubDesk/>
<SpreadPage>0</SpreadPage>
<Status/>
<Deadline>0708182230</Deadline>
<PagePrintInfo/>
<Cmyk>CMYK</Cmyk>
<Spot1/>
<Spot2/>
<Spot3/>
<CyanFilm/>
<MagFilm/>
<YelFilm/>
<BlackFilm/>
<Spot1Film/>
<Spot2Film/>
<Spot3Film/>
<PageId>MAIN#F</PageId>
<TemplatePage>
<Content>c#FolioStandard#i#</Content>
<Layout></Layout>
</TemplatePage>
<ProdForm/>
<TextSourceDir/>
<TextSourcePage/>
<RunningPage/>
<CmyDeadline/>
<ColorGrp/>
<AdRules>1</AdRules>
<CustChar/>
<CustDate/>
<Active>1</Active>
<NoMaster>0</NoMaster>
<Cust2/>
<PageType>EditorialOnly</PageType>
<Cust4/>
<Cust5/>
<Cust6/>
<Cust7/>
<Cust8/>
<Cust9/>
<Cust10/>
<Desk2/>
<Desk2NewsHole/>
<Desk2Placement/>
<Cust11/>
<NotUsed2/>
<NotUsed3/>
<Ad>
<BookingNumber>12345</BookingNumber>
<Description>Desc1</Description>
<AdRelatedInfo> </AdRelatedInfo>
<FirstPubDate>080818</FirstPubDate>
<LastPubDate>080818</LastPubDate>
<Customer>Customer</Customer>
<AdColor>Proces</AdColor>
<AdWidth>710.9</AdWidth>
<AdHeight>144.0</AdHeight>
<MatType>EPS</MatType>
<AdType>0</AdType>
<AdPos>
<XPos>0.00</XPos>
<YPos>1404.03</YPos>
</AdPos>
<AdProdInfo/>
<AdNotUsed2/>
<AdNotUsed3/>
<AdCust1/>
<AdCust2/>
<AdCust3/>
</Ad>
<AutoTypesetInfo>0:5-60</AutoTypesetInfo></Page>
<Page>
<PhysicalBook>A</PhysicalBook>
<BookPageNumber>2</BookPageNumber>
<Desk>A</Desk>
<SubDesk/>
<SpreadPage>0</SpreadPage>
<Status/>
<Deadline>0708182230</Deadline>
<PagePrintInfo/>
<Cmyk>CMYK</Cmyk>
<Spot1/>
<Spot2/>
<Spot3/>
<CyanFilm/>
<MagFilm/>
<YelFilm/>
<BlackFilm/>
<Spot1Film/>
<Spot2Film/>
<Spot3Film/>
<PageId>MAIN#1</PageId>
<TemplatePage>
<Content>c#FolioStandard#i#</Content>
<Layout></Layout>
</TemplatePage>
<ProdForm/>
<TextSourceDir/>
<TextSourcePage/>
<RunningPage/>
<CmyDeadline/>
<ColorGrp/>
<AdRules>1</AdRules>
<CustChar/>
<CustDate/>
<Active>1</Active>
<NoMaster>0</NoMaster>
<Cust2/>
<PageType>Mixed</PageType>
<Cust4/>
<Cust5/>
<Cust6/>
<Cust7/>
<Cust8/>
<Cust9/>
<Cust10/>
<Desk2/>
<Desk2NewsHole/>
<Desk2Placement/>
<Cust11/>
<NotUsed2/>
<NotUsed3/>
<Ad>
<BookingNumber>152345</BookingNumber>
<Description>Description</Description>
<AdRelatedInfo> </AdRelatedInfo>
<FirstPubDate>080818</FirstPubDate>
<LastPubDate>080818</LastPubDate>
<Customer>Customer</Customer>
<AdColor>000K</AdColor>
<AdWidth>351.9</AdWidth>
<AdHeight>360.0</AdHeight>
<MatType>EPS</MatType>
<AdType>0</AdType>
<AdPos>
<XPos>0.00</XPos>
<YPos>1188.03</YPos>
</AdPos>
<AdProdInfo/>
<AdNotUsed2/>
<AdNotUsed3/>
<AdCust1/>
<AdCust2/>
<AdCust3/>
</Ad>
<Ad>
<BookingNumber>12345</BookingNumber>
<Description>Description</Description>
<AdRelatedInfo> </AdRelatedInfo>
<FirstPubDate>080818</FirstPubDate>
<LastPubDate>080818</LastPubDate>
<Customer>Customer</Customer>
<AdColor>Proces</AdColor>
<AdWidth>351.9</AdWidth>
<AdHeight>360.0</AdHeight>
<MatType>EPS</MatType>
<AdType>0</AdType>
<AdPos>
<XPos>358.99</XPos>
<YPos>1188.03</YPos>
</AdPos>
<AdProdInfo/>
<AdNotUsed2/>
<AdNotUsed3/>
<AdCust1/>
<AdCust2/>
<AdCust3/>
</Ad>
<AutoTypesetInfo>0:5-60</AutoTypesetInfo>
</Page>
</Plan>
XSL:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:cci="http://www.ccieurope.com/xmlns/CCIPlanner"
exclude-result-prefixes="msxsl cci"
>
<xsl:output indent="yes"/>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<!-- If element name match on NotUsed2, exclude from result -->
<xsl:template match="NotUsed2" />
</xsl:stylesheet>
Expected in the resulting Page node:
<Page>
<PhysicalBook>A</PhysicalBook>
<BookPageNumber>1</BookPageNumber>
<Desk>A</Desk>
<SubDesk/>
<SpreadPage>0</SpreadPage>
<Status/>
<Deadline>0708182230</Deadline>
<PagePrintInfo/>
<Cmyk>CMYK</Cmyk>
<Spot1/>
<Spot2/>
<Spot3/>
<CyanFilm/>
<MagFilm/>
<YelFilm/>
<BlackFilm/>
<Spot1Film/>
<Spot2Film/>
<Spot3Film/>
<PageId>MAIN#F</PageId>
<TemplatePage>
<Content>c#FolioStandard#i#</Content>
<Layout></Layout>
</TemplatePage>
<ProdForm/>
<TextSourceDir/>
<TextSourcePage/>
<RunningPage/>
<CmyDeadline/>
<ColorGrp/>
<AdRules>1</AdRules>
<CustChar/>
<CustDate/>
<Active>1</Active>
<NoMaster>0</NoMaster>
<Cust2/>
<PageType>EditorialOnly</PageType>
<Cust4/>
<Cust5/>
<Cust6/>
<Cust7/>
<Cust8/>
<Cust9/>
<Cust10/>
<Desk2/>
<Desk2NewsHole/>
<Desk2Placement/>
<Cust11/>
<NotUsed3/>
<AutoTypesetInfo>0:5-60</AutoTypesetInfo>
<Ad>
<BookingNumber>12345</BookingNumber>
<Description>Desc1</Description>
<AdRelatedInfo> </AdRelatedInfo>
<FirstPubDate>080818</FirstPubDate>
<LastPubDate>080818</LastPubDate>
<Customer>Customer</Customer>
<AdColor>Proces</AdColor>
<AdWidth>710.9</AdWidth>
<AdHeight>144.0</AdHeight>
<MatType>EPS</MatType>
<AdType>0</AdType>
<AdPos>
<XPos>0.00</XPos>
<YPos>1404.03</YPos>
</AdPos>
<AdProdInfo/>
<AdNotUsed2/>
<AdNotUsed3/>
<AdCust1/>
<AdCust2/>
<AdCust3/>
</Ad>
</Page>
I can't get the code to exclude the NotUsed2 element.
I'm not sure where to begin to tackle reordering the elements within nodes.
Any help would be appreciated.
Your NotUsed2 is not being removed because you have not accounted for the fact the element is in a default namespace in the XML. Your XSLT is looking for an element with no namespace.
You have declared the relevant namespace in your XSLT, so you just need to use the relevant prefix in the template match
<xsl:template match="cci:NotUsed2" />
For moving AutoTypesetInfo after NotUsed3 you should have a template that matches NotUsed3 where you can copy both the matched node, and the AutoTypesetInfo
<xsl:template match="cci:NotUsed3">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
<xsl:copy-of select="../cci:AutoTypesetInfo" />
</xsl:template>
You would also need a template to ensure the AutoTypesetInfo still doesn't get copied in its current position too
<xsl:template match="cci:AutoTypesetInfo" />
Try this XSLT
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:cci="http://www.ccieurope.com/xmlns/CCIPlanner"
exclude-result-prefixes="msxsl cci">
<xsl:output indent="yes"/>
<xsl:template match="#* | node()" name="identity">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<!-- If element name match on NotUsed2, exclude from result -->
<xsl:template match="cci:NotUsed2" />
<xsl:template match="cci:NotUsed3">
<xsl:call-template name="identity" />
<xsl:copy-of select="../cci:AutoTypesetInfo" />
</xsl:template>
<xsl:template match="cci:AutoTypesetInfo" />
</xsl:stylesheet>
This does assume NotUsed3 is always present. If not, change the last template to this to ensure the original AutoTypesetInfo is not removed in this case.
<xsl:template match="cci:AutoTypesetInfo[../cci:NotUsed3]" />
Try below XSLT.
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:cci="http://www.ccieurope.com/xmlns/CCIPlanner"
exclude-result-prefixes="msxsl cci"
>
<xsl:output indent="yes"/>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<!-- If element name match on NotUsed2, exclude from result -->
<xsl:template match="*[local-name()='NotUsed2']" />
</xsl:stylesheet>

Checking multiple attribute values in multiple nodes with XSL

the xml is as follows.
<MyXml>
<Machine1>
<SupportedOS>
<OS1 MajorVersion=1 MinorVersion=2/>
<OS2 MajorVersion=2 MinorVersion=0/>
<OS3 MajorVersion=1 MinorVersion=1/>
<OS4 MajorVersion=2 MinorVersion=1/>
<OS5 MajorVersion=3 MinorVersion=0/>
</SupportedOS>
</Machine1>
</MyXml>
I get the OS version from some source (say MajorVersion=x1 and MinorVersion=x2) inside this XML and Add both the xml programitically.
The task is to compare the Both the Minor and Major Version of OS and olny if the both of them are same to the source only then copy the Machine node to the transformed xml.
Let me know the ways to do it. I will try to code myself.
EDIT
I want to copy the Machine Node when any one of the OS node has MajorVersion=x1 and MinorVersion=x2.
As simple as this:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="pMajor" select="1"/>
<xsl:param name="pMinor" select="2"/>
<xsl:template match="/*/*">
<xsl:copy-of select=
"self::*[*/*[#MajorVersion = $pMajor and #MinorVersion = $pMinor]]"/>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on the following XML document (the provided one is severely malformed and not useful!):
<MyXml>
<Machine1>
<SupportedOS>
<OS1 MajorVersion="1" MinorVersion="2"/>
<OS2 MajorVersion="2" MinorVersion="0"/>
<OS3 MajorVersion="1" MinorVersion="1"/>
<OS4 MajorVersion="2" MinorVersion="1"/>
<OS5 MajorVersion="3" MinorVersion="0"/>
</SupportedOS>
</Machine1>
<Machine2>
<SupportedOS>
<OS1 MajorVersion="1" MinorVersion="3"/>
<OS2 MajorVersion="2" MinorVersion="0"/>
<OS3 MajorVersion="1" MinorVersion="1"/>
<OS4 MajorVersion="2" MinorVersion="1"/>
<OS5 MajorVersion="3" MinorVersion="0"/>
</SupportedOS>
</Machine2>
</MyXml>
the wanted, correct result is produced:
<Machine1>
<SupportedOS>
<OS1 MajorVersion="1" MinorVersion="2"/>
<OS2 MajorVersion="2" MinorVersion="0"/>
<OS3 MajorVersion="1" MinorVersion="1"/>
<OS4 MajorVersion="2" MinorVersion="1"/>
<OS5 MajorVersion="3" MinorVersion="0"/>
</SupportedOS>
</Machine1>
Compare attributes if they aren't satisfying the condition .. if yes then drop them..
Or else copy them
in the below code, first template copies all nodes,
second template drops OS that is having MajorVersion not equal to 'x1' and MinorVersion not equal to 'x2'
<?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" indent="yes"/>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/MyXml/Machine1/SupportedOS/OS1[#MajorVersion != 'x1' and #MajorVersion!='x2']"/>
</xsl:stylesheet>
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml"/>
<xsl:template match="/MyXml">
<xsl:apply-templates select="//SupportedOS"/>
</xsl:template>
<xsl:template match="SupportedOS">
<xsl:for-each select="child::*">
<xsl:if test="#MajorVersion='1' and #MinorVersion='2'">
<xsl:copy-of select="//Machine1"/>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

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.

Generate XSLT to map source value structures to destination field depending on source content

I have a source list of xml in this format:
<metadata>
<metadatum>
<description>OnEnter</description>
<value>Hello World</id>
</metadatum>
<metadatum>
<description>OnLeave</description>
<value>Goodbye World</id>
</metadatum>
</metadata>
and a target structure like this:
<friendlyText>
<onEnter>[Content Here]</onEnter>
<onLeave>[Content Here]</onLeave>
</friendlyText>
Is it possible to create an XSLT that will map the 'value' field in the metadata hierarchy to the proper target node depending on the source 'description'?
I'm trying to get this done with Altova MapForce; it feels like there should be an interface to allow this, I'm just not finding it.
<?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" indent="yes"/>
<xsl:template match="metadata">
<friendlyText>
<xsl:apply-templates select="metadatum"/>
</friendlyText>
</xsl:template>
<xsl:template match="metadatum">
<xsl:element name="{description}">
<xsl:value-of select="value"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Output:
<?xml version="1.0" encoding="utf-8"?>
<friendlyText>
<OnEnter>Hello World</OnEnter>
<OnLeave>Goodbye World</OnLeave>
</friendlyText>
This transformation is a general solution that can work with any "target structure" that is in a separate XML document:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="my:my" exclude-result-prefixes="my">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="vUpper" select=
"'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
<xsl:variable name="vLower" select=
"'abcdefghijklmnopqrstuvwxyz'"/>
<my:target>
<friendlyText>
<onEnter>[Content Here]</onEnter>
<onLeave>[Content Here]</onLeave>
</friendlyText>
</my:target>
<xsl:variable name="vTarget" select="document('')/*/my:target/*"/>
<xsl:variable name="vMeta" select="/*/metadatum"/>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates select="$vTarget"/>
</xsl:template>
<xsl:template match="friendlyText/*/text()">
<xsl:value-of select=
"$vMeta[translate(description, $vLower, $vUpper)
=
translate(name(current()/..), $vLower, $vUpper)
]/value"/>
</xsl:template>
</xsl:stylesheet>
when applied on the provided XML document (corrected to be made well-formed):
<metadata>
<metadatum>
<description>OnEnter</description>
<value>Hello World</value>
</metadatum>
<metadatum>
<description>OnLeave</description>
<value>Goodbye World</value>
</metadatum>
</metadata>
produces the wanted, correct result:
<friendlyText xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:my="my:my">
<onEnter>Hello World</onEnter>
<onLeave>Goodbye World</onLeave>
</friendlyText>
Do note: Only for convenience, the "target structure" is inline here. In a real world case it would be better to keep the "target structure" in a separate file and to load it using the document() function. Only the line:
<xsl:variable name="vTarget" select="document('')/*/my:target/*"/>
will need to be changed to:
<xsl:variable name="vTarget" select="document('someFileUrl')/*"/>