Reputation: 63
Need to transform the request from system A to fint into the request of system B.
Suppose I have an XML document that looks like this from system A:
<root>
<Bundle>
<authors>
<author>
<authorID>100</authorID>
<authorName>Kathisiera</authorName>
</author>
<author>
<authorID>200</authorID>
<authorName>Bates</authorName>
</author>
<author>
<authorID>300</authorID>
<authorName>Gavin King</authorName>
</author>
</authors>
<books>
<book>
<bookOrderID>1111</bookOrderID>
<bookName>Head First Java</bookName>
<bookRefID>100</bookRefID>
</book>
<book>
<bookOrderID>5555</bookOrderID>
<bookName>Head First Servlets</bookName>
<bookRefID>200</bookRefID>
</book>
<book>
<bookOrderID>1111</bookOrderID>
<bookName>Hibernate In Action</bookName>
<bookRefID>300</bookRefID>
</book>
</books>
</Bundle>
I have to fit this request into the request structure of system B:
<root>
<Bundle>
<authors>
<author>
<authorID>100</authorID>
<authorName>Kathisiera</authorName>
</author>
<author>
<authorID>300</authorID>
<authorName>Gavin King</authorName>
</author>
</authors>
<books>
<book>
<bookOrderID>1111</bookOrderID>
<bookName>Head First Java</bookName>
<bookRefID>100</bookRefID>
</book>
<book>
<bookOrderID>1111</bookOrderID>
<bookName>Hibernate In Action</bookName>
<bookRefID>300</bookRefID>
</book>
</books>
</Bundle>
<Bundle>
<authors>
<author>
<authorID>200</authorID>
<authorName>Bates</authorName>
</author>
</authors>
<books>
<book>
<bookOrderID>5555</bookOrderID>
<bookName>Head First Servlets</bookName>
<bookRefID>200</bookRefID>
</book>
</books>
</Bundle>
First I have to group book
inside Bundle
based on bookOrderID
. Then group author
inside Bundle
by comparing bookRefID
with authorID
.
I tried usingkey() generate-id()
function of xslt. But unable to get the expected result.
Please help me out to get the solution.
Upvotes: 3
Views: 148
Reputation: 338376
Here is one way to do it:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:key name="kBook" match="book" use="bookOrderID" />
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*" />
</xsl:copy>
</xsl:template>
<xsl:template match="root">
<xsl:apply-templates mode="bundle" select="Bundle/books/book[
generate-id()
=
generate-id(key('kBook', bookOrderID)[1])
]" />
</xsl:template>
<xsl:template match="book" mode="bundle">
<xsl:variable name="bookGroup" select="key('kBook', bookOrderID)" />
<Bundle>
<authors>
<xsl:copy-of select="//author[authorID = $bookGroup/bookRefID]" />
</authors>
<books>
<xsl:copy-of select="$bookGroup" />
</books>
</Bundle>
</xsl:template>
</xsl:stylesheet>
This groups books by their bookOrderID
using an <xsl:key>
.
After that it uses a property of the =
operator to find all related autors: The =
operator compares all nodes on either side with each other. Think of it as a sort of "inner join" for node sets. This way you can copy the right nodes with a simple <xsl:copy-of>
.
Upvotes: 0
Reputation: 56212
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="k" match="book" use="bookOrderID"/>
<xsl:key name="a" match="author" use="authorID"/>
<xsl:template match="/root">
<xsl:copy>
<xsl:apply-templates select="//books"/>
</xsl:copy>
</xsl:template>
<xsl:template match="books">
<xsl:apply-templates select="book[generate-id(.) = generate-id(key('k', bookOrderID))]"/>
</xsl:template>
<xsl:template match="book">
<Bundle>
<authors>
<xsl:apply-templates select="key('a', key('k', bookOrderID)/bookRefID)"/>
</authors>
<books>
<xsl:copy-of select="key('k', bookOrderID)"/>
</books>
</Bundle>
</xsl:template>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Input:
<root>
<Bundle>
<authors>
<author>
<authorID>100</authorID>
<authorName>Kathisiera</authorName>
</author>
<author>
<authorID>200</authorID>
<authorName>Bates</authorName>
</author>
<author>
<authorID>300</authorID>
<authorName>Gavin King</authorName>
</author>
</authors>
<books>
<book>
<bookOrderID>1111</bookOrderID>
<bookName>Head First Java</bookName>
<bookRefID>100</bookRefID>
</book>
<book>
<bookOrderID>5555</bookOrderID>
<bookName>Head First Servlets</bookName>
<bookRefID>200</bookRefID>
</book>
<book>
<bookOrderID>1111</bookOrderID>
<bookName>Hibernate In Action</bookName>
<bookRefID>300</bookRefID>
</book>
</books>
</Bundle>
</root>
Output:
<root>
<Bundle>
<authors>
<author>
<authorID>100</authorID>
<authorName>Kathisiera</authorName>
</author>
<author>
<authorID>300</authorID>
<authorName>Gavin King</authorName>
</author>
</authors>
<books>
<book>
<bookOrderID>1111</bookOrderID>
<bookName>Head First Java</bookName>
<bookRefID>100</bookRefID>
</book>
<book>
<bookOrderID>1111</bookOrderID>
<bookName>Hibernate In Action</bookName>
<bookRefID>300</bookRefID>
</book>
</books>
</Bundle>
<Bundle>
<authors>
<author>
<authorID>200</authorID>
<authorName>Bates</authorName>
</author>
</authors>
<books>
<book>
<bookOrderID>5555</bookOrderID>
<bookName>Head First Servlets</bookName>
<bookRefID>200</bookRefID>
</book>
</books>
</Bundle>
</root>
Upvotes: 1