开发者

Sorting subentities in a complex XML in BizTalk

I get some data from a WebService, which looks like this

Building
     Address
     -> 开发者_C百科Office
         Name
         CreationDate
         -> Worker
              Name
              HiringDate 

Before doing further processing and transforms on this message, I need to sort the sub-nodes ("Office" and "Worker") so that all Offices are sorted by CreationDate, and then all Workers are sorted by HiringDate inside their Office.

So far the only solutions I've seen for sorting in BizTalk have been XSLT based. There are some samples that show how to sort on a simpler structure (http://www.biztalkgurus.com/newsletter/TheBizTalker-Volume-03.html) but those won't work as-is since my message has several levels.

If have no idea how to (if that is even possible) write an XSLT expression that will do this sorting while preserving the structure of the XML.

Is it possible to write such an XSLT expression? What would it look like?


Found the solution here: http://bloggingabout.net/blogs/wellink/archive/2005/12/09/10499.aspx

If we apply that technique to our example we get this XSLT

    <xsl:for-each select="Office">
        <xsl:sort select="CreationDate" data-type="text" order="ascending"/>        
        <Office>
            <xsl:copy-of select="Name"/>
            <xsl:copy-of select="CreationDate"/>
            <xsl:for-each select="Worker">
                <xsl:sort select="HiringDate" data-type="text" order="ascending"/>
                <Worker>
                    <xsl:copy-of select="Name"/>
                    <xsl:copy-of select="HiringDate"/>
                </Worker>
            </xsl:for-each>
        </Office>
    </xsl:for-each>

Then hook it up in the Map as shown below and it works fine.

Sorting subentities in a complex XML in BizTalk


You need a XSLT copy templates for all tags exclude Office and Worker, and sorting templates for that tags. eg Copy templates:

<xsl:template match="node()">
    <xsl:if test="name()">
        <xsl:element name="{name()}">
            <xsl:apply-templates select="@*|node()"/>
        </xsl:element>
    </xsl:if>
</xsl:template>

<xsl:template match="text()">
    <xsl:value-of select="."/>
</xsl:template>

<xsl:template match="@*">
    <xsl:copy>
        <xsl:value-of select="."/>
    </xsl:copy>
</xsl:template>

And sorting templates:

<xsl:match="office_parent_tag_as_i_understand_Building">
    <xsl:apply-templates select="Office">
        <xsl:sort select="CreationDate" data-type="text" order="ascending"/>
    </xsl:foreach>
</xsl:template>

& analog for Worker tag

<xsl:match="worker_parent_tag_as_i_understand_Office">
    <xsl:apply-templates select="Worker">
        <xsl:sort select="HiringDate" data-type="text" order="ascending"/>
    </xsl:foreach>
</xsl:template>

Don't forget that xsl:sort works only with numeric and text data, for sorting by date you need to convert date to int or string

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜