views:

17

answers:

2

I have been given an XML document in a rather strange format and I need to load it into a DataSet, but unsurprisingly I get an error when I try to do so. I can see how I could transform the document into something that would work, but I'm kinda going around in circles with the XSLT stuff...

The document looks something like this:

<map>
    <entry key = "status">ok</entry>
    <entry key = "pageNum">1</entry>
    <entry key = "title">DocTitle</entry>
    <entry key = "stuff">
        <map>
            <entry key = "id">171</entry>
            <entry key = "name">StackOverflow</entry>
            <entry key = "timeZone">America/New_York</entry>
        </map>
        <map>
            <entry key = "id">172</entry>
            <entry key = "name">StackOverflow2</entry>
            <entry key = "timeZone">America/New_York</entry>
        </map>
    </entry>
</map>

and I would like to transform it into something more like this:

<map>
    <status>ok</status>
    <pageNum>1</pageNum>
    <title>DocTitle</title>
    <stuff>
        <map>
            <id>171</id>
            <name>StackOverflow</name>
            <timeZone>America/New_York</timeZone>
        </map>
        <map>
            <id>172</id>
            <name>StackOverflow2</name>
            <timeZone>America/New_York</timeZone>
        </map>
    </stuff>
</map>

I have all the code in place to run it through an XSLT transform and process the output, but I can't get the transform itself to produce anything sensible. I really don't think it's as difficult as I'm making it, and I would be eternally grateful if some wise soul could throw together something that would work.

Or maybe just point me to an example or something that I could modify...

Thanks.

+2  A: 

This transformation:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="entry[@key]">
   <xsl:element name="{@key}">
     <xsl:apply-templates/>
   </xsl:element>
 </xsl:template>
</xsl:stylesheet>

when applied on the provided XML document:

<map>
    <entry key = "status">ok</entry>
    <entry key = "pageNum">1</entry>
    <entry key = "title">DocTitle</entry>
    <entry key = "stuff">
        <map>
            <entry key = "id">171</entry>
            <entry key = "name">StackOverflow</entry>
            <entry key = "timeZone">America/New_York</entry>
        </map>
        <map>
            <entry key = "id">172</entry>
            <entry key = "name">StackOverflow2</entry>
            <entry key = "timeZone">America/New_York</entry>
        </map>
    </entry>
</map>

produces the wanted, correct result:

<map>
    <status>ok</status>
    <pageNum>1</pageNum>
    <title>DocTitle</title>
    <stuff>
        <map>
            <id>171</id>
            <name>StackOverflow</name>
            <timeZone>America/New_York</timeZone>
        </map>
        <map>
            <id>172</id>
            <name>StackOverflow2</name>
            <timeZone>America/New_York</timeZone>
        </map>
    </stuff>
</map>
Dimitre Novatchev
Wow! That is exactlty what I needed - and a quick response too!
Miszou
@Miszou: Glad that this solution was useful. At SO the way to express gratitude is by accepting and upvoting the answer. :)
Dimitre Novatchev
+1 Good answer.
Alejandro
I meant to say "Thanks!" as well, but the comment was accepted when I hit enter for a new line and I couldn't seem to get it back again. Apparently, I accidentally logged out or something weird... anyway, thanks again! (And upvoted!)
Miszou
A: 
<xsl:stylesheet 
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
    exclude-result-prefixes="xs">

<xsl:template match="*">
    <xsl:copy>
        <xsl:apply-templates/>
    </xsl:copy>
</xsl:template>

<xsl:template match="//entry">
        <xsl:variable name="key" select="@key"/>
        <xsl:element name="{$key}">
                <xsl:apply-templates/>
        </xsl:element>
</xsl:template>

</xsl:stylesheet>
sweetfa
@sweetfa: use code markup. The starting `//` operator is no needed in patterns.
Alejandro
@sweetfa: Why XSLT 2.0? No XSLT 2.0 - only feature is used in your solution. In all such cases it is good to express the solution as XSLT 1.0 so that it is clear the majority of readers can use it.
Dimitre Novatchev