genox Posted July 11, 2010 Share Posted July 11, 2010 Hi All,A newbie to the forum and the world of XML/XSLTI'm trying to create a XSLT script to convert from one XML format to another (cXML is the target format) for a system integration project.I want to be able to map values in the source XML tags to the destination cXML tags as necessary but am stumbling on problems retrieving the right elementsHere comes the code...Source XML to be converted <?xml version="1.0" encoding="UTF-8"?> <PublishMXPO_GOSOP xmlns="http://www.ibm.com/maximo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" creationDateTime="2010-07-07T10:22:53+01:00" transLanguage="EN" baseLanguage="EN" messageID="1278494573441131060" maximoVersion="7 1 20090627-0754 V7115-149" event="0"> <MXPO_GOSOPSet> <PO> <BILLTO>BAKEWELL</BILLTO> <BILLTOATTN>PMPRBOWNUSR</BILLTOATTN> </PO> </MXPO_GOSOPSet> </PublishMXPO_GOSOP> XSL script <?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:xalan="http://xml.apache.org/xslt"> <xsl:output method="xml" version="1.0" doctype-system="http://xml.cxml.org/schemas/cXML/1.2.020/cXML.dtd" indent="yes"/> <xsl:variable name="version">1.2.020</xsl:variable> <xsl:template match="/PublishMXPO_GOSOP"> <xsl:apply-templates select="PublishMXPO_GOSOP"/> </xsl:template> <xsl:template match="*"> <xsl:variable name="messageID" select="@messageID"/> <xsl:variable name="timestamp" select="@creationDateTime"/> <xsl:variable name="version" select="$version"/> <cXML payloadID="{$messageID}" timestamp="{$timestamp}" version="{$version}" > <BILLADDRESS><xsl:value-of select="*"/></BILLADDRESS> <BILLTOPERSON><xsl:value-of select="PublishMXPO_GOSOP/MXPO_GOSOPSet/PO/BILLTOATTN"/></BILLTOPERSON> </cXML> </xsl:template> </xsl:stylesheet> Current output XML <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE cXML SYSTEM "http://xml.cxml.org/schemas/cXML/1.2.020/cXML.dtd"> <cXML xmlns:xalan="http://xml.apache.org/xslt" version="1.2.020" timestamp="2010-07-07T10:22:53+01:00" payloadID="1278494573441131060"> <BILLADDRESS> BAKEWELL PMPRBOWNUSR </BILLADDRESS> <BILLTOPERSON/> </cXML> I want to be able to split the two (and more) element values out into their respective target tags as below. Any clues on how to do this?This is the format I want to get to: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE cXML SYSTEM "http://xml.cxml.org/schemas/cXML/1.2.020/cXML.dtd"> <cXML xmlns:xalan="http://xml.apache.org/xslt" version="1.2.020" timestamp="2010-07-07T10:22:53+01:00" payloadID="1278494573441131060"> <BILLADDRESS>BAKEWELL</BILLADDRESS> <BILLTOPERSON>PMPRBOWNUSR<BILLTOPERSON/> </cXML> I've only managed to get anything returned from the source XML file by using xsl:value-of select="*". Using an XPATH expression like in <BILLTOATTN> does not workAlso, when I change the first template-match statement to / from /PublishMXPO_GOSOP I lose everything in the conversion except the xml version encoding header? I thought this should select all the nodes in the whole document?Any advice on this is really appreciatedCheersEugene Link to comment Share on other sites More sharing options...
Martin Honnen Posted July 11, 2010 Share Posted July 11, 2010 There is a namespace declaration xmlns="http://www.ibm.com/maximo"on the root element of your input XML and you need to take that into account when writing the stylesheet. With XSLT/XPath 1.0 a path 'foo' selects an element with local-name 'foo' in no namespace. To select an element in a namespace you need to bind a prefix to the namespace URI and use that prefix to qualify element names e.g. <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:mx="http://www.ibm.com/maximo" exclude-result-prefixes="mx" version="1.0"> <xsl:template match="mx:PublishMXPO_GOSOP"> <cXML> <xsl:apply-templates select="mx:MXPO_GOSOPSet/mx:PO/*"/> </cXML> </xsl:template> <xsl:template match="mx:BILLTO"> <BILLADDRESS><xsl:value-of select="."/></BILLADDRESS> </xsl:template> <!-- add further templates here --></xsl:stylesheet> Link to comment Share on other sites More sharing options...
boen_robot Posted July 11, 2010 Share Posted July 11, 2010 XSLT starts processing at the root node, and goes in on every node on every level.Also, your source XML contains namespaces, so your XSLT needs to be made aware of them.Try <?xml version="1.0" encoding="utf-8"?><xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:xalan="http://xml.apache.org/xslt" xmlns:m="http://www.ibm.com/maximo" exclude-result-prefixes="m"> <xsl:output method="xml" version="1.0" doctype-system="http://xml.cxml.org/schemas/cXML/1.2.020/cXML.dtd" indent="yes"/> <xsl:variable name="version">1.2.020</xsl:variable> <xsl:template match="/m:PublishMXPO_GOSOP"> <cXML payloadID="{@messageID}" timestamp="{@creationDateTime}" version="{$version}"> <xsl:apply-templates/> </cXML> </xsl:template> <xsl:template match="m:BILLTO|m:BILLTOATTN"><xsl:value-of select="." /></xsl:template></xsl:stylesheet> [edit]Yeah... Martin beated me to it [/edit] Link to comment Share on other sites More sharing options...
genox Posted July 12, 2010 Author Share Posted July 12, 2010 Thanks guys for the help, its really appreciated and got me off to a good start with this.Of course my problem is a little more complex that first thought... I need to get all my elements within the <cXML> tags and in between some others as wellThe basic structure of the target XML is <cXML><Header><From><Credential></Credential><Identity></Identity></From><To><Credential></Credential><Identity></Identity></To></Header><Request><OrderRequest><OrderRequestHeader/><Total><Money></Money></Total><ShipTo><Address><Name></Name><PostalAddress>...</PostalAddress><Email></Email></Address></ShipTo><BillTo><Address><Name></Name><PostalAddress>...</PostalAddress><Email></Email></Address></BillTo><Contact></Contact><Comments></Comments></OrderRequestHeader><ItemOut><ItemID></ItemID><ItemDetail>...</ItemDetail></ItemOut></Request></OrderRequest></cXML> Where ... denotes some more attributes not shown hereI need to be able to match attributes from the source XML within the structure above in the target, file - can I use xsl:template match the way that has been described? I found you cannot nest xsl:template match tags like this: <xsl:template match="mx:ORDERDATE"> <Request deploymentMode="test"> <OrderRequest> <ShipTo> <xsl:element name="OrderRequestHeader"> <xsl:attribute name="orderDate"><xsl:value-of select="."/></xsl:attribute> </xsl:element> <xsl:template match="mx:ADDRESS1"> <xsl:element name="Name"> <xsl:attribute name="xml:lang">en</xsl:attribute> <xsl:value-of select="."/> </xsl:element> </ShipTo> </OrderRequest> </Request> </xsl:template></xsl:template> I've had to resort to re-listing the parent tags for each xsl:template match tag to avoid the error - such as: <xsl:template match="mx:ORDERDATE"> <Request deploymentMode="test"> <OrderRequest> <ShipTo> <xsl:element name="OrderRequestHeader"> <xsl:attribute name="orderDate"><xsl:value-of select="."/></xsl:attribute> <xsl:attribute name="orderType">regular</xsl:attribute> <xsl:attribute name="orderVersion">1</xsl:attribute> <xsl:attribute name="type">new</xsl:attribute> </xsl:element> </ShipTo> </OrderRequest> </Request> </xsl:template><xsl:template match="mx:ADDRESS1"> <Request deploymentMode="test"> <OrderRequest> <ShipTo> <xsl:element name="Name"> <xsl:attribute name="xml:lang">en</xsl:attribute> <xsl:value-of select="."/> </xsl:element> </ShipTo> </OrderRequest> </Request> </xsl:template> What am I doing wrong here? Is there a easier way of doing this?Thanks again Link to comment Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.