on 12-21-2006 12:30 PM
Hello all,
here is the sample structure of the import file:
MT_PO
DT_PO
DocumentHeader
ItemHeader
ItemDetail
DT_PO
DocumentHeader
ItemHeader
ItemDetail
ItemDetail
ItemHeader
ItemDetail
So, as you see, DocumentHeader is 1:1, ItemHeader is 1:1 and ItemDetail is 1:n cardinality. The problem is that ItemHeader and ItemDetail are on the same level in the structure, and I need transformation to structure like this:
MT_PO
DT_PO
DocumentHeader
Items
Item
ItemHeader
ItemDetail
DT_PO
DocumentHeader
Items
Item
ItemHeader
ItemDetail
ItemDetail
Item
ItemHeader
ItemDetail
Following transformation does not work because (of course) for each ItemHeader it reads all ItemDetail in the parrent node:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<MT_PO>
<xsl:for-each select="MT_PO/DT_PO">
<DT_PO>
<xsl:copy-of select="DocumentHeader"/>
<Items>
<xsl:for-each select="ItemHeader">
<Item>
<xsl:copy-of select="."/>
<xsl:for-each select="../ItemDetail">
<xsl:copy-of select="."/>
</xsl:for-each>
</Item>
</xsl:for-each>
</Items>
</DT_PO>
</xsl:for-each>
</MT_PO>
</xsl:template>
</xsl:stylesheet>
Does anybody has idea how to do that?
Thanks in advance!
Best regards,
Ivan
I would recommend looking into writing a user-defined function in Java that will allow you to perform "context changes", and manipulate the parent-child structure of the target message.
Hopefully this blog will provide a good intro to the topic:
/people/harrison.holland5/blog/2006/12/08/mapping-context-changes-in-xi
You can use two functions calls in a "queue" user-defined function.
(1) result.addValue();
(2) result.addContextChange();
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
After looking at your requirements again, it seems like you may be able to avoid a custom java function by using the splitByValue graphical mapping function, which is pretty standard. Assuming that you are not going to be doing much other manipulation of the source fields. The splitByValue function will simply take the source field and perform the context change for you everytime it finds a new instance of the child-node. You do have to make sure to map the parent 1:1 to each other in order for this to work.
First, check out <a href="http://help.sap.com/saphelp_nw04/helpdata/en/21/3bb8c495125e4eb5969f0377885fe0/content.htm">this link</a>. That gives a good simple example of how to use splitByValue.
Now, for your scenario to take a source message like this:
MT_PO
DT_PO
DocumentHeader
ItemHeader
ItemDetail
DT_PO
DocumentHeader
ItemHeader
ItemDetail
ItemDetail
ItemHeader
ItemDetail
and produce a target message like this:
MT_PO
DT_PO
DocumentHeader
Items
Item
ItemHeader
ItemDetail
DT_PO
DocumentHeader
Items
Item
ItemHeader
ItemDetail
ItemDetail
Item
ItemHeader
ItemDetail
I would do a mapping something like this:
(source) MT_PO :: (target) MT_PO
(source) DT_PO :: (target) DT_PO
(source) DocumentHeader :: (target) DocumentHeader
(source) ItemHeader : splitByValue : (target) \Items\item\ItemHeader
(source) ItemDetail & ItemHeader: UDF : (target) \Items\item\ItemDetail
The user defined function should be defined as a type queue with two inputs, the ItemDetail and the ItemHeader. Then you will loop through the values as shown in the first blog I linked regarding <a href="/people/harrison.holland5/blog/2006/12/08/mapping-context-changes-in-xi changes</a> and perform a result.addContextChange() everytime a new header comes in, but only pass back the values of ItemDetail with result.addValue().
Good luck
Hi,
fortunately, there is an XSLT solution for the problem
[code]<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes"/>
<xsl:template match="/">
<MT_PO>
<xsl:apply-templates select="MT_PO/DT_PO"/>
</MT_PO>
</xsl:template>
<xsl:template match="DT_PO">
<DT_PO>
<xsl:copy-of select="MT_PO/DT_PO/DocumentHeader"/>
<Items>
<xsl:for-each select="ItemHeader">
<Item>
<xsl:copy-of select="."/>
<xsl:variable name="headerId" select="generate-id(.)"/>
<xsl:for-each select="following-sibling::ItemDetail[generate-id(preceding-sibling::ItemHeader[1])=$headerId]">
<xsl:copy-of select="."/>
</xsl:for-each>
</Item>
</xsl:for-each>
</Items>
</DT_PO>
</xsl:template>
</xsl:stylesheet>[/code]
Regards,
Ivan
User | Count |
---|---|
87 | |
10 | |
10 | |
10 | |
7 | |
6 | |
6 | |
5 | |
5 | |
4 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.