XSL to suppress xml declaration conditonally (fails) - xslt

I fail to suppress the xml declaration with my following xsl. I want a completely empty xml when OWNER=0000080070:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" />
<xsl:template match="/">
<xsl:choose>
<xsl:when test="//IDOC/ZSCWM_TU[OWNER='0000080070']">
</xsl:when>
<xsl:otherwise>
<xsl:text disable-output-escaping="yes"><?xml version="1.0" encoding="UTF-8"?>
</xsl:text>
</xsl:otherwise>
</xsl:choose>
<xsl:apply-templates/>
</xsl:template>
<!-- Special template -->
<xsl:template match="/*[//IDOC/ZSCWM_TU[OWNER='0000080070']]">
</xsl:template>
<!-- Default Template -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Input xml:
<?xml version="1.0" encoding="UTF-8"?>
<ZSCWM_-TU_LOADLIST>
<IDOC BEGIN="1">
<EDI_DC40 SEGMENT="1">
<TABNAM>EDI_DC40</TABNAM>
</EDI_DC40>
<ZSCWM_TU SEGMENT="1">
<OWNER>0000080070</OWNER>
</ZSCWM_TU>
</IDOC>
</ZSCWM_-TU_LOADLIST>
Current output:
<?xml version="1.0" encoding="UTF-8"?>
Required output:
BLANK XML
I must be making a stupid mistake :(
Kind regards,
Mike

If you're using an XSLT 2.0 processor such as Saxon then I would recommend
<xsl:template match="/">
<xsl:result-document omit-xml-declaration=
"{if (//IDOC/ZSCWM_TU[OWNER='0000080070']) then 'yes' else 'no'}">
<xsl:apply-templates/>
</xsl:result-document>
</xsl:template>

Related

Sending value with different tag XSLT

is there any chance can sending value to output other node response, with different path from there input request. i have input and response tag like this
Input Request:
<Root>
<Items>
<Item1>Rambutan12</Item1>
</Items>
</Root>
and i try with this code for add new node with additional info at Response
i try like this
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fn="http://www.w3.org/2005/xpath-functions">
<xsl:output method="text"/>
<xsl:template match="/">
<Root>
<ItemsResponse>
<xsl:call-templates select="items">
<xsl:with-param name="item1s" select="//Root/Items/Item1"/>
</xsl:call-templates>
</ItemsResponse>
</Root>
</xst:template>
<xsl:template name="items">
<xsl:param name="item1s"/>
<xsl:variable name="information">
<xsl:choose>
<xsl:when test="fn:matches($item1s, '^[a-zA-Z]*$') ">
<Item1><xsl:value-of select="$item1s"/></Item1>
</xsl:when>
<xsl:otherwise>
<xsl:copy>
<Item1><xsl:value-of select="$item1s"/></Item1>
<xsl:apply-templates select="Item1Information"/>
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
</xsl:template>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="Item1Information">
<xsl:copy>
<Item1Information>Wrong Failed Format Input</Item1Information>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Expected Result was like this
<Root>
<ItemsResponse>
<Item1>Rambutan12</Item1>
<Item1Information>Input Failed Format</ItemInformation>
</ItemsResponse>
</Root>
Any tips like for this case, thanks
It is very difficult to understand what your question is.
On the off-chance that I am guessing correctly, and that you want to add an error warning when Item1 contains any characters other than the 26 letters of the English alphabet, then you could do simply:
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="/Root">
<Root>
<ItemsResponse>
<xsl:copy-of select="Items/Item1"/>
<xsl:if test="translate(Items/Item1, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', '')">
<Item1Information>Input Failed Format</Item1Information>
</xsl:if>
</ItemsResponse>
</Root>
</xsl:template>
</xsl:stylesheet>

XSLT - add prefix for namespace

Here's my input XML:
<?xml version="1.0" encoding="UTF-8"?>
<Sync
xmlns="http://schema.infor.com/InforOAGIS/2" languageCode="en-US" versionID="2.8.0">
<Data>
<ID>0001</ID>
<Text>ABCD</Text>
</Data>
</Sync>
And here's my expected outcome:
<?xml version="1.0" encoding="UTF-8"?>
<ns0:Sync xmlns:ns0="http://schema.infor.com/InforOAGIS/2"
languageCode="en-US"
versionID="2.8.0">
<DataArea xmlns:dns="http://schema.infor.com/InforOAGIS/2" xmlns="">
<ID>0001</ID>
<Text>ABCD</Text>
</DataArea>
</ns0:Sync>
My current XSLT as below (https://xsltfiddle.liberty-development.net/nbiE19N).
There are 2 problems:
I have the extra xmlns="" in DataArea element. I only want to add the dns namespace.
I cannot add the ns0 prefix for my namespace
<xsl:stylesheet version="2.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="/*:Sync">
<xsl:copy>
<xsl:copy-of select="#*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*:Sync/*:Data">
<DataArea>
<xsl:namespace name="dns" select="'http://schema.infor.com/InforOAGIS/2'"/>
<ID>
<xsl:value-of select="/*:Sync/*:Data/*:ID"/>
</ID>
<Text>
<xsl:value-of select="/*:Sync/*:Data/*:Text"/>
</Text>
</DataArea>
</xsl:template>
</xsl:stylesheet>
Any suggestion is appreciated!
Does this return the expected result:
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xpath-default-namespace="http://schema.infor.com/InforOAGIS/2">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/Sync">
<ns0:Sync xmlns:ns0="http://schema.infor.com/InforOAGIS/2">
<xsl:copy-of select="#*"/>
<xsl:apply-templates/>
</ns0:Sync>
</xsl:template>
<xsl:template match="Data">
<DataArea xmlns:dns="http://schema.infor.com/InforOAGIS/2">
<xsl:apply-templates/>
</DataArea>
</xsl:template>
<xsl:template match="*">
<xsl:element name="{local-name()}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
P.S. I am not sure why you need the xmlns:dns="http://schema.infor.com/InforOAGIS/2" declaration; it's not being used anywhere.

Duplicate a node and child elements if it occurs only once

I need to duplicate a node and its child elements, if it occurs only once in the xml. Otherwise, the xml shouldn't be modified. For ex, in the below xml, if <dataList> occurs only once then duplicate it one more time. If not, don't change the xml at all. Only XSLT 1.0 please.
Input XML
<?xml version="1.0" encoding="UTF-8"?>
<API>
<Token/>
<root>
<dataList>
<addressOne>1</addressOne>
<addressTwo/>
<bkdn/>
</dataList>
</root>
</API>
Expected output xml
<?xml version="1.0" encoding="UTF-8"?>
<API>
<Token/>
<root>
<dataList>
<addressOne>1</addressOne>
<addressTwo/>
<bkdn/>
</dataList>
<dataList>
<addressOne>1</addressOne>
<addressTwo/>
<bkdn/>
</dataList>
</root>
</API>
As per my understanding here i want to solve it:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="1.0">
<xsl:output indent="yes"/>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="root">
<xsl:copy>
<xsl:choose>
<!-- If you are looking for the dataList occurance then use count -->
<xsl:when test="count(dataList) = 1">
<!-- If you are looking for the dataList/addressOne value = 1 occurance then use below -->
<!-- <xsl:when test="dataList/addressOne=1"> -->
<xsl:apply-templates select="dataList"/>
<xsl:apply-templates select="dataList"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="dataList"/>
</xsl:otherwise>
</xsl:choose>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

XSLT add root node if not exists

I have some XML and having a difficult time transforming it.
Example XML:
<?xml version="1.0" encoding="utf-8"?>
<Cars xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Car> ... </Car>
</Cars>
I would like to change it to:
<?xml version="1.0" encoding="utf-8"?>
<Depot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Cars>
<Car> ... </Car>
</Cars>
</Depot>
Sounds simple enough but the problem is some data is already in the expected format, in which case I don't want to apply the transform. How do I achieve this?
EDIT
Some starting XSLT:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" mlns:xsi="http://www.w3.org/2001/XMLSchema-
instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="Cars">
<Depot>
<Cars>
<xsl:apply-templates select="*"/>
</Cars>
</Depot>
</xsl:template>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
I think you only want to match Cars if it is the root element, so instead of your template matching "Cars", change it to match "/Cars"
<xsl:template match="/Cars">
Try this XSLT (which I have slightly amended to get the first template to call the identity template)
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" >
<xsl:output method="xml" indent="yes" />
<xsl:template match="/Cars">
<Depot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsl:call-template name="identity" />
</Depot>
</xsl:template>
<xsl:template match="#*|node()" name="identity">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
I think that it is just necessary to use a choose in the root template to test if the node Depot exists, if not create it:
<xsl:template match="/">
<xsl:choose>
<xsl:when test="Depot">
<xsl:apply-templates/>
</xsl:when>
<xsl:otherwise>
<Depot>
<xsl:apply-templates/>
</Depot>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()" />
</xsl:copy>
</xsl:template>
This also gives same output.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" >
<xsl:template match="Cars">
<Depot>
<xsl:copy-of select="."/>
</Depot>
</xsl:template>
</xsl:stylesheet>

remove child node namespace and copy another node into a variable

I am trying to copy all the child elements of soap:Header element into a variable and also trying to remove PricingRequest empty namespace (xmlns="http://www.ama.net") and output only PricingRequest part of xml. I am able to remove PricingRequest empty namespace and get proper output but not able to store soap:Header child elements into a variable, is it possible to copy child elements of soap:Header into a variable ?
INPUT XML:
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap ="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header xmlns="http://www.ama.net/1axml-msg/schema/msg-header-1_0.xsd">
<MessageHeader ResponseRequested="true" version="1.0" Terminate="true" Reverse="true" id="09B5581A" soap:mustUnderstand="1">
<From>1ASI</From>
<To>1ASRINSAIG</To>
<TimeStamp>
<GenerationTime>2014-10-22T12:41:38Z</GenerationTime>
</TimeStamp>
</MessageHeader>
</soap:Header>
<soap:Body>
<PricingRequest xmlns="http://www.ama.net">
<originatorSection>
<deliverySystem>
<companyId>1A</companyId>
<cityCode>MUC</cityCode>
</deliverySystem>
</originatorSection>
</PricingRequest>
</soap:Body>
</soap:Envelope>
XSLT :
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:x="http://www.ama.net" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- <xsl:template match="/*[local-name()='Envelope']">
<xsl:variable name="SOAPHeader" select="/soap:Header/node()" />
<xsl:text> MessageHeader INFO:<xsl:copy-of select="$SOAPHeader"/> </xsl:text>
</xsl:template> -->
<xsl:template match="*">
<xsl:element name="{name()}">
<xsl:copy-of select="#*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="*[not(ancestor-or-self::x:PricingRequest)]">
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
getting expecting OUTPUT but not able to copy soap:Header into a variable:
<PricingRequest>
<originatorSection>
<deliverySystem>
<companyId>1A</companyId>
<cityCode>MUC</cityCode>
</deliverySystem>
</originatorSection>
</PricingRequest>
Try;
<xsl:template match="/">
<xsl:variable name="SOAPHeader" select="/soap:Envelope/soap:Header/node()" />
<xsl:text>MessageHeader INFO:</xsl:text>
<xsl:copy-of select="$SOAPHeader"/>
</xsl:template>
Note:
<xsl:text> cannot contain child elements;
your version has conflicting templates for soap:Envelope.
the following code worked the way i wanted. I am able to copy soap:Header child elements in a variable and also removed PricingRequest namespace in the output
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.ama.net/1axml-msg/schema/msg-header-1_0.xsd"
xmlns:ns2="http://www.ama.net" exclude-result-prefixes="ns1 ns2 soap">
<xsl:template match="ns1:* | ns2:*| soap:*">
<xsl:element name="{local-name()}">
<xsl:copy-of select="#*" />
<xsl:apply-templates />
</xsl:element>
</xsl:template>
<xsl:template match="/">
<xsl:variable name="SOAPHeader">
<xsl:apply-templates select="/soap:Envelope/soap:Header/node()" />
</xsl:variable>
<xsl:text>HeaderInfo:</xsl:text>
<xsl:copy-of select="$SOAPHeader" />
<xsl:apply-templates select="/soap:Envelope/soap:Body/node()" />
</xsl:template>
</xsl:stylesheet>
OUTPUT I am getting:
<?xml version="1.0"?>
HeaderInfo:
<MessageHeader xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" ResponseRequested="true" version="1.0" Terminate="true" Reverse="true" id="09B5581A" soap:mustUnderstand="1">
<From>1ASI</From>
<To>1ASRINSAIG</To>
<TimeStamp>
<GenerationTime>2014-10-22T12:41:38Z</GenerationTime>
</TimeStamp>
</MessageHeader>
<PricingRequest>
<originatorSection>
<deliverySystem>
<companyId>1A</companyId>
<cityCode>MUC</cityCode>
</deliverySystem>
</originatorSection>
</PricingRequest>