Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Westi on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Replace Root Node 1

Status
Not open for further replies.

edster86

Programmer
Nov 1, 2007
6
GB
Hi, i'm a bit new to all this!!

I have an xml export from MS access however it is written with a microsoft root node - how can i replace this with one that matches the schema?

At the moment i've got:

<?xml version="1.0"?>

<xsl:stylesheet version="1.0" xmlns:xsl=" <xsl:template match="/">
<NEWROOTNODE>
<xsl:copy-of select="child::node()" />
</NEWROOTNODE>
</xsl:template>
</xsl:stylesheet>

However this copys all the data including the old root node.
 
You may try this.
[tt]
<xsl:stylesheet version="1.0" xmlns:xsl="<xsl:eek:utput method="xml" indent="yes" encoding="utf-8" />
<xsl:template match="/">
<xsl:apply-templates select="*|comment()|processing-instruction()" />
</xsl:template>
<xsl:template match="comment()|processing-instruction()">
<xsl:copy-of select="." />
</xsl:template>
<xsl:template match="*[count(parent::*) = 0]">
<xsl:element name="newroot" namespace="{namespace-uri()}">
<xsl:copy-of select="@*|namespace::*" />
<xsl:apply-templates select="*|comment()|processing-instruction()" />
</xsl:element>
</xsl:template>
<xsl:template match="*[not(count(parent::*) = 0)]">
<xsl:copy-of select="." />
</xsl:template>
</xsl:stylesheet>
[/tt]
 
Thanks for that, it nearly all worked perfectly.

The out put now is:

- <MYNEWROOTNODE>

- <dataroot generated="2007-10-28T11:51:19" xmlns:eek:d="urn:schemas-microsoft-com:eek:fficedata">

+ <HTT:Inventory>

</dataroot>
</MYNEWROOTNODE>

So the data root still seems to exist but is just moved down a node? Any ideas?
 
There might be some complication from namespace declaration etc... but I really don't see how the old root could possibly remain! Could you recheck?
 
Sorry about that, my fault - i was checking the wrong output file!!

Thanks that works well.

The only thing is that it has left some of the old root node namespace in the new one eg.

<eso:NEWROOT generated="2007-10-28T11:51:19" xmlns:eek:d="urn:schemas-microsoft-com:eek:fficedata" xmlns:eso="xmlns:eso= xmlns:xsi= xsi:schemaLocation=
I dont want the "generated" string or the "xmlns:eek:d" string.

Any ideas?

Many thanks.
 
[1] To take out specific attribute, it is simple.
><xsl:copy-of select="@*|namespace::*" />
[tt]<xsl:copy-of select="@*[name() != 'generated']" />
<xsl:copy-of select="namespace::*" />[/tt]

[2] The other part, I do not fully understand the need rightaway. I'll re-read the requirement a bit later: have to do something else the moment.
 
Will give that a go, really appreciate you time and help

Thanks.
 
[2] The figurative eso:NEWROOT looks very strange in the xmlns:eso="..." part. I suppose it is just because some over-editing. If the prefixed-od namespace is something deliquant, orphan namespace (appearing in the old root - this is a condition for the following to make sense and not appearing in any of the child elements) that should be eliminated from the transformed, you can do this.

[2.1] Declaring it in the xsl:stylesheet element. The prefix can be anything because it is of no generic undertone, let's say make it od-anyname. Then add it to the value of the exclude-result-prefixes attribute.
[tt]
<xsl:stylesheet xmlns:xsl=" ...
xmlns:eek:d-anyname="urn:schemas-microsoft-com:eek:fficedata"
...
exclude-result-prefixes="od-anyname"
>
[/tt]
If it is really an orphan namespace, it would disappear from the output. I would not be surprised the above failed, because the conditions mentioned along the reasoning are very specific and may not correspond to the concrete case you're dealing with.
 
Sorry i'm a bit confused!!
I have the root:

<eso:NMAReports generated="2007-10-28T11:51:19" xmlns:eek:d="urn:schemas-microsoft-com:eek:fficedata" xmlns:eso="
currently generated from my xsl.

What is the code i need to remove these extra elements of generated and xmlns:eek:d?
 
>What is the code i need to remove these extra elements of generated and xmlns:eek:d?
I rephrase.
[1'] Break the italic line into the two lines shown in [1].
[2'] Add the two attributes to the xsl:stylesheet element shown in [2.1]. od-anyname is just trying to show you the prefix is of no canonical value, you can call it od (same prefix used in the xml document) or any thing else (od-anyname for instance or x or y or z: any name token). To make it concrete, use "od" (at the place of "od-anyname") in the xsl document would be just fine.
Is it now clear?
 
Thanks, thats got rid of the 'generated' bit now which is good.

The xmlns:eek:d...... bit is still there though, my xsl code is:

<xsl:stylesheet version="1.0"
xmlns:xsl="xmlns:eek:d="urn:schemas-microsoft-com:eek:fficedata"
exclude-result-prefixes="od" >

<xsl:eek:utput method="xml" indent="yes" encoding="UTF-8" />

That look right? Also at the moment it keeps transforming into UTF-16 - any ideas why?

Thanks a million.
 
[3] Upon re-reading the general setting, I think the proposed approach of [2] would fail. The namespace and its prefix od are declared in the original xml document and that fact calls for a different approach effectively. The transformed elements should be reconstructed more fundmentally. The below should replace [2]. Try it. Its working would also depend on od being orphan, if not, there might be further complication.
[tt]
<xsl:stylesheet version="1.0" xmlns:xsl="<xsl:eek:utput method="xml" indent="yes" encoding="utf-8" />
<xsl:template match="/">
<xsl:apply-templates select="*|comment()|processing-instruction()" />
</xsl:template>
<xsl:template match="@*|comment()|processing-instruction()">
<xsl:copy-of select="." />
</xsl:template>
<xsl:template match="*[count(parent::*) = 0]">
<xsl:element name="newroot" namespace="{namespace-uri()}">
<xsl:copy-of select="@*[name() != 'generated']" />
<xsl:copy-of select="namespace::*[local-name() != 'od']" />
<xsl:apply-templates select="*|comment()|processing-instruction()" />
</xsl:element>
</xsl:template>
<xsl:template match="*[not(count(parent::*) = 0)]">
<xsl:element name="{name()}" namespace="{namespace-uri()}">
<xsl:copy-of select="namespace::*[local-name() != 'od']" />
<xsl:apply-templates select="*|@*|processing-instruction()|comment()" />
</xsl:template>
</xsl:stylesheet>
[/tt]
[3.1] Since the elements are effectively reconstructed, it makes the treatement of non-root elements a lot more closely resemble the treatment of the root. I keep it separated in order to make a smoother transition from [2].
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top