I'm mapping home, work and mobile number nodes from the source schema to the home, work and mobile node in the destination schema.
I need to ensure that the data matches destination pattern (No space, punctuation, leading zeros, matching [+0][0-9]*. Can this be achieved via XSLT?
Source
<HTelephone>01656 123 123</HTelephone>
<WTelephone>01656-123-123</WTelephone>
<MTelephone>+447656 123 123</MTelephone>
Destination
<HTelephone>01656123123</HTelephone>
<WTelephone>01656123123</WTelephone>
<MTelephone>+447656123123</MTelephone>
Current Inline XSLT Call Template
<xsl:template name="MNo" xmlns:msxsl="urn:schemas-microsoft-com:xslt" >
<xsl:param name="inTelNo"/>
<xsl:element name="MTelephone" >
<xsl:value-of select="concat('+', translate($inTelNo, translate($inTelNo,'0123456789',''), ''))"/>
</xsl:element>
We need to validation the first character to allow a 0 or + also, any ideas?
Assuming correct input ( a root element to make it well-formed XML) use the concat() and translate functions to change the strings.
Input
<?xml version="1.0" encoding="utf-8"?>
<root>
<HTelephone>01656 123 123</HTelephone>
<WTelephone>01656 123 123</WTelephone>
<MTelephone>01656 123 123</MTelephone>
</root>
Stylesheet
<?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" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/root">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="root/*">
<xsl:copy>
<xsl:value-of select="concat('+',translate(.,' ',''))"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Output
<?xml version="1.0" encoding="utf-8"?>
<root>
<HTelephone>+01656123123</HTelephone>
<WTelephone>+01656123123</WTelephone>
<MTelephone>+01656123123</MTelephone>
</root>
Related
I have a simple XML response, like
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<searchRetrieveResponse xmlns="http://www.loc.gov/zing/srw/">
<numberOfRecords>1</numberOfRecords>
<records>
<record>
<recordData>
<kitodo xmlns="http://meta.kitodo.org/v1/">
<metadata name="key1">value1</metadata>
<metadata name="key2">value2</metadata>
<metadata name="key3">value3</metadata>
</kitodo>
</recordData>
</record>
</records>
</searchRetrieveResponse>
which I want to transform to this by XSLT
<?xml version="1.0" encoding="utf-8"?>
<mets:mdWrap xmlns:kitodo="http://meta.kitodo.org/v1/"
xmlns:mets="http://www.loc.gov/METS/"
xmlns:srw="http://www.loc.gov/zing/srw/"
MDTYPE="OTHER"
OTHERMDTYPE="Kitodo">
<mets:xmlData>
<kitodo:kitodo>
<kitodo:metadata name="key1">value1</kitodo:metadata>
<kitodo:metadata name="key2">value2</kitodo:metadata>
<kitodo:metadata name="key3">value3</kitodo:metadata>
</kitodo:kitodo>
</mets:xmlData>
</mets:mdWrap>
That is, I want to remove the outside tree searchRetrieveResponse/records/record/recordData, replace it with mdWrap/xmlData and move the contained data node there.
I have a quite short XSLT for it:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:kitodo="http://meta.kitodo.org/v1/" xmlns:mets="http://www.loc.gov/METS/" xmlns:srw="http://www.loc.gov/zing/srw/">
<xsl:output method="xml" indent="yes" encoding="utf-8"/>
<xsl:strip-space elements="*"/>
<xsl:template match="srw:recordData">
<mets:mdWrap MDTYPE="OTHER" OTHERMDTYPE="Kitodo">
<mets:xmlData>
<xsl:apply-templates select="#*|node()"/>
</mets:xmlData>
</mets:mdWrap>
</xsl:template>
<!-- pass-through rule -->
<xsl:template match="#*|node()">
<xsl:apply-templates select="#*|node()"/>
</xsl:template>
</xsl:stylesheet>
However, what I get is:
<?xml version="1.0" encoding="utf-8"?>
<mets:mdWrap xmlns:kitodo="http://meta.kitodo.org/v1/"
xmlns:mets="http://www.loc.gov/METS/"
xmlns:srw="http://www.loc.gov/zing/srw/"
MDTYPE="OTHER"
OTHERMDTYPE="Kitodo">
<mets:xmlData/>
</mets:mdWrap>
Obviously, the template match="srw:recordData" does match, otherwise I would get an empty result. However, the contained apply-templates doesn’t output anything. (I also tried an <xsl:apply-templates/> without a select="" attribute, but it doesn’t output anything either.) What am I missing?
XSLT processor is net.sf.saxon.TransformerFactoryImpl (Java)
I think nothing happens when you are applying templates inside xmlData. There are no templates that would match descendant nodes.
Try using copy-of:
<xsl:template match="srw:recordData">
<mets:mdWrap MDTYPE="OTHER" OTHERMDTYPE="Kitodo">
<mets:xmlData>
<xsl:copy-of select="kitodo:kitodo"/>
</mets:xmlData>
</mets:mdWrap>
</xsl:template>
The problem is not with the xsl:apply-templates instruction. It is with the template being applied. Your "pass-through rule" does not write anything to the output. You probably meant to have the identity transform template in that place - which goes like this:
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
I read through forums and i am unable to understand why the output is empty. It might be a simple thing i am missing.
I tried debugging in VS 2017 and it does not give any output any help in this matter is appreciated. IF i input only the ns0:EFACT_D96A_ORDERS_EAN008 node as an input to XSLT the output comes with the "test" content
<?xml version="1.0" encoding="UTF-16"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:var="http://schemas.microsoft.com/BizTalk/2003/var" exclude-result-prefixes="msxsl var s0 userCSharp" version="1.0" xmlns:ns1="http://Microsoft.LobServices.Sap/2007/03/Types/Idoc/3/ORDERS05//740" xmlns:ns0="http://Microsoft.LobServices.Sap/2007/03/Idoc/3/ORDERS05//740/Send" xmlns:ns2="http://Microsoft.LobServices.Sap/2007/03/Types/Idoc/Common/" xmlns:s0="http://schemas.microsoft.com/BizTalk/EDI/EDIFACT/2006" xmlns:ns3="http://schemas.microsoft.com/2003/10/Serialization/" xmlns:userCSharp="http://schemas.microsoft.com/BizTalk/2003/userCSharp" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ins0="http://schemas.microsoft.com/BizTalk/EDI/EDIFACT/2006/InterchangeXML">
<xsl:output omit-xml-declaration="yes" method="xml" version="1.0" />
<xsl:template match="/">
<xsl:apply-templates select="/s0:EFACT_D96A_ORDERS_EAN008" />
</xsl:template>
<xsl:template match="/s0:EFACT_D96A_ORDERS_EAN008">
<ns0:Send>
<ns0:idocData>
Test
</ns0:idocData>
</ns0:Send>
</xsl:template>
</xsl:stylesheet>
Input file-
<ins0:EdifactInterchangeXml DelimiterSetSerializedData="39:-1:-1:43:58:63:-1:46:-1" xmlns:ins0="http://schemas.microsoft.com/BizTalk/EDI/EDIFACT/2006/InterchangeXML">
<ns0:UNA xmlns:ns0="http://schemas.microsoft.com/Edi/EdifactServiceSchema">
<UNA1>58</UNA1>
</ns0:UNA>
<ns0:UNB xmlns:ns0="http://schemas.microsoft.com/Edi/EdifactServiceSchema">
<UNB1>
<UNB1.1>ABCD</UNB1.1>
<UNB1.2>5</UNB1.2>
</UNB1>
</ns0:UNB>
<TransactionSetGroup>
<TransactionSet DocType="http://schemas.microsoft.com/BizTalk/EDI/EDIFACT/2006#EFACT_D96A_ORDERS_EAN008">
<ns0:EFACT_D96A_ORDERS_EAN008 xmlns:ns0="http://schemas.microsoft.com/BizTalk/EDI/EDIFACT/2006">
</ns0:EFACT_D96A_ORDERS_EAN008>
</TransactionSet>
</TransactionSetGroup>
<ns0:UNZ xmlns:ns0="http://schemas.microsoft.com/Edi/EdifactServiceSchema">
<UNZ1>1</UNZ1>
<UNZ2>86</UNZ2>
</ns0:UNZ>
</ins0:EdifactInterchangeXml>
A forward slash / at the start of the expression matches the document node, so doing select="/s0:EFACT_D96A_ORDERS_EAN008" will only select s0:EFACT_D96A_ORDERS_EAN008 if it is a child of the document node. i.e. if it is the root element, which it isn't.
To select s0:EFACT_D96A_ORDERS_EAN008 regardless of where it is in the document do this...
<xsl:apply-templates select="//s0:EFACT_D96A_ORDERS_EAN008" />
You also need to remove the single forward slash from the match expression too (You don't need the double-slashes in the match expression, as the match will work regardless of where the element is in the document)
Try this XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:var="http://schemas.microsoft.com/BizTalk/2003/var" exclude-result-prefixes="msxsl var s0 userCSharp" version="1.0" xmlns:ns1="http://Microsoft.LobServices.Sap/2007/03/Types/Idoc/3/ORDERS05//740" xmlns:ns0="http://Microsoft.LobServices.Sap/2007/03/Idoc/3/ORDERS05//740/Send" xmlns:ns2="http://Microsoft.LobServices.Sap/2007/03/Types/Idoc/Common/" xmlns:s0="http://schemas.microsoft.com/BizTalk/EDI/EDIFACT/2006" xmlns:ns3="http://schemas.microsoft.com/2003/10/Serialization/" xmlns:userCSharp="http://schemas.microsoft.com/BizTalk/2003/userCSharp" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ins0="http://schemas.microsoft.com/BizTalk/EDI/EDIFACT/2006/InterchangeXML">
<xsl:output omit-xml-declaration="yes" method="xml" version="1.0" />
<xsl:template match="/">
<xsl:apply-templates select="//s0:EFACT_D96A_ORDERS_EAN008" />
</xsl:template>
<xsl:template match="s0:EFACT_D96A_ORDERS_EAN008">
<ns0:Send>
<ns0:idocData>
Test
</ns0:idocData>
</ns0:Send>
</xsl:template>
</xsl:stylesheet>
How can I get the value 'four' in XSLT?
<root>
<entry>(one,two,three,four,five,six)</entry>
</root>
Thanks in advance.
You didn't specify the XSLT version, so I assume version 2.0.
I also assume that word four is only a "marker", stating from which place
take the result string (between the 3rd and 4th comma).
To get the fragment you want, you can:
Use tokenize function to "cut" the whole content of entry
into pieces, using a comma as the cutting pattern.
Take the fourth element of the result array.
This expression can be used e.g. in a template matching entry.
So the example script can look like below:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="UTF-8" indent="yes" />
<xsl:template match="entry">
<xsl:copy>
<xsl:value-of select="tokenize(., ',')[4]"/>
</xsl:copy>
</xsl:template>
<xsl:template match="#*|node()">
<xsl:copy><xsl:apply-templates select="#*|node()"/></xsl:copy>
</xsl:template>
</xsl:transform>
For your input XML it gives:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<entry>four</entry>
</root>
I need to copy a subnode from a XML to a certain node of a new XML in a Biztalk Map using XSLT.
Consider the following input XML:
<?xml version="1.0" encoding="UTF-8"?>
<ns0:root xmlns:ns0="http://not/useful/data/">
<ns0:notuseful>
<ns0:foo></ns0:foo>
<ns0:foo2></ns0:foo2>
<ns0:blabla></ns0:blabla>
</ns0:notuseful>
<ns0:data>
<ns1:usefulDataList xmlns:ns1="http://useful/data/">
<ns1:usefulData>
<ns1:usefulChild1></ns1:usefulChild1>
<ns1:usefulChild2></ns1:usefulChild2>
<ns1:usefulChild3></ns1:usefulChild3>
<ns1:usefulChild4></ns1:usefulChild4>
<ns1:usefulChild5></ns1:usefulChild5>
</ns1:usefulData>
</ns1:usefulDataList>
</ns0:data>
<ns0:root>
What I need is to extract the node called "usefulDataList", so I need to copy it in a new XML like this one:
<?xml version="1.0" encoding="UTF-8"?>
<ns2:root2 xmln:ns2="http://new/xml">
<ns2:blabla>
<ns2:stuff />
</ns2:blabla>
<ns2:data>
<ns2:usefulDataList>
<ns2:usefulData>
<ns2:usefulChild1></ns2:usefulChild1>
<ns2:usefulChild2></ns2:usefulChild2>
<ns2:usefulChild3></ns2:usefulChild3>
<ns2:usefulChild4></ns2:usefulChild4>
<ns2:usefulChild5></ns2:usefulChild5>
</ns2:usefulData>
</ns2:usefulDataList>
</ns2:data>
</ns2:root2>
This should be done inside a Biztalk Functoid, as you see namespaces from source and target are diferent.
I'm an absolute beginner with XSLT, and I've been doing some tests, but I've something wrong with my XSLT expressions:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns2="http://new/xml">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
<xsl:template name="testTemplate" match="//*[local-name() = 'usefulDataList ']">
<xsl:element name="ns0:usefulDataList " namespace="">
<xsl:apply-templates mode="copy-no-ns" select="usefulDataList"/>
</xsl:element>
</xsl:template>
<xsl:template mode="copy-no-ns" match="*">
<xsl:element name="{name(.)}" namespace="{namespace-uri(.)}">
<xsl:copy-of select="#*"/>
<xsl:apply-templates mode="copy-no-ns"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
I'd appreciate any tip, with XSLT or Biztalk mapper. I don't like linking a huge amount of fields one by one if I can solve it with a XSLT expression.
Greetings.
Beware you had a space in *[local-name() = 'usefulDataList ']" so that would never match. this works:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns2="http://new/xml">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<ns2:root>
<ns2:blabla>
<ns2:stuff />
</ns2:blabla>
<ns2:data>
<xsl:apply-templates mode="copy-no-ns" select="//*[local-name() = 'usefulDataList']"/>
</ns2:data>
</ns2:root>
</xsl:template>
<xsl:template mode="copy-no-ns" match="*">
<xsl:element name="ns2:{local-name(.)}">
<xsl:copy-of select="#*"/>
<xsl:apply-templates mode="copy-no-ns"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
I am new to XSLT I am trying to transform a name value pair to its corresponding XML. This feature is primarily used in case of special extensions to a standard.
The file I want to transform is the following. There are no spaces expected in any of the extNames.
<?xml version="1.0" encoding="UTF-8"?>
<extensionItems xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ExtensionItems.xsd">
<extensionsItem>
<extName> callCode</extName>
<extValue>1</extValue>
<extType>integer</extType>
</extensionsItem>
<extensionsItem>
<extName>callbackType</extName>
<extValue>All</extValue>
<extType>string</extType>
</extensionsItem>
<extensionsItem>
<extName>callbackEmail</extName>
<extValue>me#mine.org</extValue>
<extType>string</extType>
</extensionsItem>
</extensionItems>
to the following:
<ODEventNotificationExtraField>
<callCode> 1</callCode>
<callbackType> All </callbackType>
<callbackEmail> me#mine.org </callbackEmail>
</ODEventNotificationExtraField>
The following stylesheet produces the desired result:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:template match="extensionItems">
<ODEventNotificationExtraField>
<xsl:apply-templates/>
</ODEventNotificationExtraField>
</xsl:template>
<xsl:template match="extensionsItem">
<xsl:element name="{extName}">
<xsl:value-of select="extValue"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>