Remove Namespace from XML Output whilst using 1 XSLT - xslt

I am using Crystal Report 2011 Export using XSLT and cannot use the tag namespace-alias in the XSLT for some reason.
I have the following XSLT :-
<xsl:namespace-alias stylesheet-prefix="b" result-prefix="#default"/>
<xsl:template match="/b:CrystalReport">
<root>
<xsl:for-each select="b:Details">
<person>
<VRN><xsl:value-of select="b:Section/b:Field[#Name='ITMVEHICLEREGNUM1']/b:FormattedValue"/></VRN>
<Make><xsl:value-of select="b:Section/b:Field[#Name='ITMMANUDESC1']/b:FormattedValue"/></Make>
<Model><xsl:value-of select="b:Section/b:Field[#Name='ITMODELDESC1']/b:FormattedValue"/></Model>
<PolicyNumber><xsl:value-of select="b:Section/b:Field[#Name='POLEXTERNAL11']/b:FormattedValue"/></PolicyNumber>
<Title><xsl:value-of select="b:Section/b:Field[#Name='TITDESCRIPTION1']/b:FormattedValue"/></Title>
<FirstName><xsl:value-of select="b:Section/b:Field[#Name='CLIFIRST1']/b:FormattedValue"/></FirstName>
<LastName><xsl:value-of select="b:Section/b:Field[#Name='CLISURN1']/b:FormattedValue"/></LastName>
<PostCode><xsl:value-of select="b:Section/b:Field[#Name='ADRPOSTCODE1']/b:FormattedValue"/></PostCode>
<CoverStartDate><xsl:value-of select="b:Section/b:Field[#Name='POLRENDATE1']/b:FormattedValue"/></CoverStartDate>
<CoverEndDate><xsl:value-of select="b:Section/b:Field[#Name='POLENDDATE1']/b:FormattedValue"/></CoverEndDate>
<FullyComp><xsl:value-of select="b:Section/b:Field[#Name='ITMCOVERTYPECDE1']/b:FormattedValue"/></FullyComp>
<GlassLimit>500</GlassLimit>
<GlassExcess>75</GlassExcess>
<VatReg><xsl:value-of select="b:Section/b:Field[#Name='CLIVATREG1']/b:FormattedValue"/></VatReg>
<AccidentDamageExecess>N/A</AccidentDamageExecess>
<RepairExcess>0.00</RepairExcess>
<Insurer><xsl:value-of select="b:Section/b:Field[#Name='INSNAME1']/b:FormattedValue"/></Insurer>
<Referral><xsl:value-of select="b:Section/b:Field[#Name='CENDESC1']/b:FormattedValue"/></Referral>
</person>
</xsl:for-each>
</root>
</xsl:template>
</xsl:stylesheet>
The output looks like :-
<root xmlns:b="urn:crystal-reports:schemas:report-detail">
<person>
<VRN>XXXXXX</VRN>
<Make>AUSTIN</Make>
<Model>A35</Model>
<PolicyNumber>XXXXXXXX</PolicyNumber>
<Title>Mr</Title>
<FirstName>Gareth</FirstName>
<LastName>Jones</LastName>
<PostCode>AL23 6TR</PostCode>
<CoverStartDate>06.04.2011</CoverStartDate>
<CoverEndDate>05.04.2012</CoverEndDate>
<FullyComp>01</FullyComp>
<GlassLimit>500</GlassLimit>
<GlassExcess>75</GlassExcess>
<VatReg></VatReg>
<AccidentDamageExecess>N/A</AccidentDamageExecess>
<RepairExcess>0.00</RepairExcess>
<Insurer>My Insurer</Insurer>
<Referral>Direct</Referral>
</person>
</root>
I need to be able to remove the namespace from the tag and can only use 1 XSLT to do it.
Any help appreciated.
Thanks
Craig

You don't need to use namespace-alias here. The result is already in the null namespace, but if you want to suppress the b namespace declaration, you just need to use exclude-result-prefixes:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:b="urn:crystal-reports:schemas:report-detail"
exclude-result-prefixes="b">

Related

XSLT - select a node from a complex xml file

I have an XML file below where I need to get the text inside of the <Description> tag under the <Checklist> tag where the <Sequence> tag has the text 40. How to achieve it?
<?xml version="1.0" encoding="UTF-8"?>
<SyncMaintenanceOrder>
<DataArea>
<MaintenanceOrder>
<MaintenanceOrderHeader>
<DocumentID>
<ID accountingEntity="AT">1105442</ID>
</DocumentID>
<Description>Routine Bridge Inspection - S6</Description>
<PriorityCode>2</PriorityCode>
<ReportedDateTime>2020-04-29T20:21:27Z</ReportedDateTime>
</MaintenanceOrderHeader>
<MaintenanceOrderLine>
<LineNumber>10</LineNumber>
<RemainingDuration>PT8H0M0S</RemainingDuration>
<ActivityDeferredIndicator>false</ActivityDeferredIndicator>
<UserArea>
<EamCheckListInfo>
<CheckList>
<CheckListItem>
<Sequence>40</Sequence>
<Description>Half joints (Superstructure elements)</Description>
</CheckListItem>
<CheckListItem>
<Sequence>160</Sequence>
<Description>Substructure drainage (Durability elements)</Description>
</CheckListItem>
<CheckListItem>
<Sequence>60</Sequence>
<Description>Parapet beam or cantilever (Superstructure elements)</Description>
</CheckListItem>
</CheckList>
</EamCheckListInfo>
</UserArea>
</MaintenanceOrderLine>
</MaintenanceOrder>
</DataArea>
</SyncMaintenanceOrder>
I need sample of an XSLT code for selecting only the text node described above.
I'm not sure I really get your question.
This will print the Description of the CheckListItem which has a Sequence of 40:
<xsl:value-of select="//CheckListItem/Sequence[text()='40']/../Description"/>
Try it here: https://xsltfiddle.liberty-development.net/ehVZvvZ
Try the below code
<xsl:value-of select="*[local-name(.)='SyncMaintenanceOrder']/*[local-name(.)='DataArea']/*[local-name(.)='MaintenanceOrder']/*[local-name(.)='MaintenanceOrderLine']/*[local-name(.)='UserArea']/*[local-name(.)='EamCheckListInfo']/*[local-name(.)='CheckList']/*[local-name(.)='CheckListItem']/*[local-name(.)='Sequence'][text() = '40']/../*[local-name(.)='Description']" />

calling one xslt file from base xslt - xslt1.0

I went through many other similar questions and answers in stackoverflow. But still not able to resolve the issue. If anyone can help me with it that would be really great.I am using call template to call one small xslt file from my larger xslt
My small xslt(WorkOrders.xsl) is very simple. Below is the part of my xslt:
<xsl:template match="GetWorkOrder">
<tns:Work>
<tns:description>
<xsl:value-of select="//ns0:WORKORDERS_ITEM/ns0:DESCRIPTION"/>
</tns:description>
<tns:workOrderNumber>
<xsl:value-of select="//ns0:WORKORDERS_ITEM/ns0:WORKORDER"/>
</tns:workOrderNumber>
</tns:Work>
</xsl:template>
I want to call WorkOrder.xsl from my base xslt. i am using the import statement
part of my base xslt. (i have got rid of the extra xml definitions to shorten the xslt for this question)
<xsl:stylesheet version="1.0" xmlns:oraxsl="http://www.oracle.com/XSL/Transform/java">
<xsl:import href="../Transformation/WorkOrders.xsl"/>
<oracle-xsl-mapper:schema>
<!--SPECIFICATION OF MAP SOURCES AND TARGETS, DO NOT MODIFY.-->
<oracle-xsl-mapper:mapSources>
<oracle-xsl-mapper:source type="XSD">
<oracle-xsl-mapper:schema location="../Schema/Sample.xsd"/>
<oracle-xsl-mapper:rootElement name="OutputParameters"
namespace="****"/>
</oracle-xsl-mapper:source>
</oracle-xsl-mapper:mapSources>
<oracle-xsl-mapper:mapTargets>
<oracle-xsl-mapper:target type="XSD">
<oracle-xsl-mapper:schema location="../Schema/Sample1.xsd"/>
<oracle-xsl-mapper:rootElement name="GetResponse" namespace="*****"/>
</oracle-xsl-mapper:target>
</oracle-xsl-mapper:mapTargets>
<!--GENERATED BY ORACLE XSL MAPPER 12.1.3.0.0(XSLT Build 140529.0700.0211) AT [THU SEP 26 14:08:57 EDT 2019].-->
</oracle-xsl-mapper:schema>
<!--User Editing allowed BELOW this line - DO NOT DELETE THIS LINE-->
<xsl:template match="/">
<tns:GetResponse>
<tns:Response>
<Work>
<xsl:call-template name="GetWorkOrder"></xsl:call-template>
</Work>
</tns:Response>
</tns:GetResponse>
</xsl:template>
</xsl:stylesheet>
I receive an error message saying GetWorkOrder template is been called but not defied. Not sure what i am missing
Your template isn't named GridWalkOrder, you've defined it as matching an element of that name rather than naming the template. Use
<xsl:template name="GetWorkOrder">
instead.

XSLT to Concatenate Empty Values

We have a requirement that requires us to list out all the empty values from the incoming xml. I have searched but all I could find was listing non-null values, trying to use that for our xml is not returning the required results.
Here is the xml that we will receive and I want to be able to concatenate all the null values from this xml and print. Kindly assist.
<?xml version = "1.0" encoding = "UTF-8"?>
<Output>
<Rows>
<ns0:I2NA xmlns:ns0 = "http://www.example.com/schemas/Schema.xsd">
<ns0:Organization>108</ns0:Organization>
<ns0:AccountNumber>1231231231231231233 </ns0:AccountNumber>
<ns0:Status>0</ns0:Status>
<ns0:VipStatus>0</ns0:VipStatus>
<ns0:TypeOfIdNo>1</ns0:TypeOfIdNo>
<ns0:IdNo>2303111450 </ns0:IdNo>
<ns0:HomePhone>123456 </ns0:HomePhone>
<ns0:Employer> </ns0:Employer>
<ns0:EmployersPhone>123456 </ns0:EmployersPhone>
<ns0:FaxPhone>123456 </ns0:FaxPhone>
<ns0:MobileNo>0568520421 </ns0:MobileNo>
<ns0:CountryCode> </ns0:CountryCode>
<ns0:PostalCode> </ns0:PostalCode>
<ns0:Position> </ns0:Position>
<ns0:MaritalStatus>0</ns0:MaritalStatus>
<ns0:DateOfBirth>00000000</ns0:DateOfBirth>
<ns0:EmailAddrs> </ns0:EmailAddrs>
<ns0:UserCode1> </ns0:UserCode1>
<ns0:NationalityCode> </ns0:NationalityCode>
<ns0:NameLine1>ABC </ns0:NameLine1>
<ns0:NameLine2> </ns0:NameLine2>
<ns0:NameLine3> </ns0:NameLine3>
<ns0:ChDob> </ns0:ChDob>
<ns0:AddressLine1>USA </ns0:AddressLine1>
<ns0:AddressLine2>USA </ns0:AddressLine2>
<ns0:AddressLine3>USA </ns0:AddressLine3>
<ns0:AddressLine4>USA </ns0:AddressLine4>
<ns0:City> </ns0:City>
<ns0:State> </ns0:State>
<ns0:GenderCode>0</ns0:GenderCode>
<ns0:StatementNotifIndi> </ns0:StatementNotifIndi>
<ns0:Nationality> </ns0:Nationality>
<ns0:County> </ns0:County>
<ns0:LastName>John </ns0:LastName>
<ns0:MiddleName> </ns0:MiddleName>
<ns0:FirstName>SHAN MATHEW </ns0:FirstName>
<ns0:LangPref> </ns0:LangPref>
</ns0:I2NA>
</Rows>
<EOF>true</EOF>
When the XSLT is applied, we would like to receive the below string as output.
Status,Employer,CountryCode,PostalCode,Position,EmailAddrs,UserCode1,NationalityCode,NameLine2,NameLine3,ChDob,City,State,StatementNotifIndi,Nationality,County,MiddleName,LangPref
Thanks!
Use <xsl:value-of select="//*[not(*) and not(normalize-space())]/local-name()" separator=","/>. But I don't understand why your sample string starts with Status while the XML has a value <ns0:Status>0</ns0:Status> for that field.
With XSLT 1.0 you need a bit of more code:
<xsl:for-each select="//*[not(*) and not(normalize-space())]">
<xsl:if test="position() > 1"><xsl:text>.</xsl:text></xsl:if>
<xsl:value-of select="local-name()"/>
</xsl:for-each>

Processing hl7 type message using xslt or regex, or combination of two (XSLT 1.0)

so I have this hl7 type message that I have to transform using either regex or xslt or combination of two.
Format of this message is DateTime(as in YYYYMMDDHHMMSS)^UnitName^room^bed|). Each location is separated with a pipe, so each person can have one or multiple locations.
And the messages looks like this( when a patient has only one location):
20130602201605^Some Hospital^ABFG^411|
End xml result should look like this:
<Location>
<item>
<when>20130602201605</when>
<UnitName>Some Hospital</UnitName>
<room>ABFG</room>
<bed>411</bed>
</item>
</Location>
I would probably use substring type of function if it was only one location.
The problem I am running into is when there is more than one. I am relatively new to xslt and regex in general so I don't know how to use recursion in these instances.
So if I have a message like this with multiple locations:
20130601003203^GBMC^XXYZ^110|20130602130600^Sanai^ABC^|20130602150003^John Hopkins^J615^A|
The end result should be:
<Location>
<item>
<when>0130601003203</when>
<UnitName>GBMC</UnitName>
<room>XXYZ</room>
<bed>110</bed>
</item>
<item>
<when>20130602130600</when>
<UnitName>Sanai</UnitName>
<room>ABC</room>
<bed></bed>
</item>
<item>
<when>20130602150003</when>
<UnitName>John Hopkins</UnitName>
<room>J615</room>
<bed>A</bed>
</item>
</Location>
So how would I solve this? Thanks in advance.
Given that your Hl7 message is "|^~\&" encoded and not in an XML format, it is not clear how you will be using an XSLT 1.0 processor for your task. Can you describe your processing pipeline in greater detail? Your snippets are not complete messages, and it is not clear whether you will be starting with complete messages or attempting to parse isolated fields handed to a larger processing task through parameters or something.
If your processing starts with a complete HL7 message, I would suggest looking into the HAPI project, or a similar set of libraries, to have the messages converted from |^~\& to </> format, then invoking your XSLT on that version of the data. (You could also use the HAPI libraries in a full-Java solution. In either case, there are code examples at the HAPI site and at an Apache site on HL7.) If you are not interested in using Java at all, but are open to partial non-XSLT solutions, there are other projects that provide similar serialization options (e.g., Net::HL7 for Perl, nHAPI for VB/C#, etc.).
If you have isolated "|^~\&" encoded data in an otherwise XML formatted file, then I would suggest looking into the str:tokenize function in the XSLT 1.0 exslt functions. (XSLT 2.0 has a built-in tokenize function.) You can have str:tokenize split your data on the field or component separators, then create elements using the tokenized substrings.
Here is a stylesheet
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:str="http://exslt.org/strings"
extension-element-prefixes="str"
version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="data">
<Location>
<xsl:for-each select="str:tokenize(.,'|')">
<xsl:call-template name="handle-field">
<xsl:with-param name="field" select="."/>
</xsl:call-template>
</xsl:for-each>
</Location>
</xsl:template>
<xsl:template name="handle-field">
<xsl:param name="field"/>
<xsl:variable name="components" select="str:tokenize($field,'^')"/>
<item>
<when><xsl:value-of select="$components[1]"/></when>
<UnitName><xsl:value-of select="$components[2]"/></UnitName>
<room><xsl:value-of select="$components[3]"/></room>
<bed><xsl:value-of select="$components[4]"/></bed>
</item>
</xsl:template>
</xsl:stylesheet>
that runs over this input
<?xml version="1.0" encoding="UTF-8"?>
<data>20130601003203^GBMC^XXYZ^110|20130602130600^Sanai^ABC^|20130602150003^John Hopkins^J615^A|</data>
to produce this output with xsltproc:
<?xml version="1.0"?>
<Location>
<item>
<when>20130601003203</when>
<UnitName>GBMC</UnitName>
<room>XXYZ</room>
<bed>110</bed>
</item>
<item>
<when>20130602130600</when>
<UnitName>Sanai</UnitName>
<room>ABC</room>
<bed/>
</item>
<item>
<when>20130602150003</when>
<UnitName>John Hopkins</UnitName>
<room>J615</room>
<bed>A</bed>
</item>
</Location>
Your source message is in a string form, you need to create a parser that uses regex to split the message based on first pipes and then carat. refer to Unable to parse ^ character which has my original code for the parser and the solution gives a different approach to it.
After you have individual elements you need to add it to your xml as nodes.

XSLT - Two seperate data sources merged into one XSLT

I've have two XML data sources which are completly seperate. UserDetails.xml and UserSites.xml.
The UserDetails.xml contains:
<a:UserDetails>
<a:user>
<a:username>Clow</a:username>
<a:userid>9834</a:userid>
</a:user>
<a:user>
<a:username>Adam</a:username>
<a:userid>9867</a:userid>
</a:user>
</a:UserDetails>
UserSites.xml contains:
<a:UserSites>
<a:site>
<a:createdby>9834</a:userid>
<a:type>blog</a:type>
</a:site>
<a:site>
<a:createdby>9867</a:username>
<a:type>web</a:type>
</a:site>
What I would like to do is use data in both of these data sources to indicate which users have sites created and what type of site they have.
How can this be made possible in XSLT 1.0?
Use the document function to access nodes in an external document
For example, the following stylesheet applied to UserDetails.xml:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:a="a">
<xsl:template match="/">
<test>
<xsl:value-of
select="document('UserSites.xml')/a:UserSites/a:site/a:createdby"/>
</test>
</xsl:template>
</xsl:stylesheet>
Outputs the following result from UserSites.xml:
9834
Note: Your example XML is not well-formed, so I had to make minor adjustments before processing.