removing namespaces from an XML document

Matt (archive)

Usenet Archive
Joined
Jan 13, 2000
Messages
739
Reaction score
0
Hello,

I have an XML document similar to the following:

<DataItems>
<Data xmlns="http://www.me.com">
<DataInformation xmlns:a="http://www.me.com/ASettings" xsi:type="a:Stuff1"> <a:Name>Matt</a:Name> <a:TN>555-5555</a:TN> </DataInformation> </Data> <Data xmlns="http://www.me.com"> <DataInformation xmlns:b="http://www.me.com/BSettings" xsi:type="b:Stuff2"> <b:Name>Bob</b:Name> <b:TN>555-6666</b:TN> </DataInformation> </Data> </DataItems>

What I would like to do is take all the namespaces and throw them in the garbage! For example, I want to remove the xmlns attribute from the Data node, I want to remove all the "a" and "b" prefixes from all the nodes, etc. I want the final outcome to look like the following:

<DataItems>
<Data>
<DataInformation type="Stuff1">
<Name>Matt</Name>
<TN>555-5555</TN>
</DataInformation>
</Data>
<Data>
<DataInformation type="Stuff2">
<Name>Bob</Name>
<TN>555-6666</TN>
</DataInformation>
</Data>
</DataItems>

I am using C++ and Microsoft's xml implementation (DOM). I have no choice but to use the raw Microsoft interfaces.

Does anyone have a good idea of how to do this?

Thanks,
Matt
 

Martin Honnen

Usenet Archive
Joined
Apr 8, 2000
Messages
6,174
Reaction score
0
Matt said:
I have an XML document similar to the following:

<DataItems>
<Data xmlns="http://www.me.com">
<DataInformation xmlns:a="http://www.me.com/ASettings" xsi:type="a:Stuff1"> <a:Name>Matt</a:Name> <a:TN>555-5555</a:TN> </DataInformation> </Data> <Data xmlns="http://www.me.com"> <DataInformation xmlns:b="http://www.me.com/BSettings" xsi:type="b:Stuff2"> <b:Name>Bob</b:Name> <b:TN>555-6666</b:TN> </DataInformation> </Data> </DataItems>

What I would like to do is take all the namespaces and throw them in the garbage! For example, I want to remove the xmlns attribute from the Data node, I want to remove all the "a" and "b" prefixes from all the nodes, etc. I want the final outcome to look like the following:

<DataItems>
<Data>
<DataInformation type="Stuff1">
<Name>Matt</Name>
<TN>555-5555</TN>
</DataInformation>
</Data>
<Data>
<DataInformation type="Stuff2">
<Name>Bob</Name>
<TN>555-6666</TN>
</DataInformation>
</Data>
</DataItems>

I am using C++ and Microsoft's xml implementation (DOM). I have no choice but to use the raw Microsoft interfaces.

Does anyone have a good idea of how to do this?

XSLT is good for such tasks, the following stylesheet throws out all namespace prefixes from element and attribute nodes:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

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

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

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

<xsl:template match="@*">
<xsl:attribute name="{local-name}"><xsl:value-of select="." /></xsl:attribute> </xsl:template>

<xsl:template match="text | processing-instruction | comment"> <xsl:copy /> </xsl:template>

</xsl:stylesheet>

The transformation is done with a JavaScript and MSXML 4 as follows (I know you asked about C++ but I have never used MSXML with C++ thus I hope you will be able to translate the JavaScript into C++):

var sourceDocument = new ActiveXObject('Msxml2.DOMDocument.4.0'); sourceDocument.async = false; sourceDocument.preserveWhiteSpace = true; sourceDocument.validateOnParse = false; var loaded = sourceDocument.load('test20040408.xml'); if (loaded) { var xslDocument = new ActiveXObject('Msxml2.DOMDocument.4.0'); xslDocument.async = false; loaded = xslDocument.load('test20040408Xsl.xml'); if (loaded) { var resultDocument = new ActiveXObject('Msxml2.DOMDocument.4.0'); sourceDocument.transformNodeToObject(xslDocument, resultDocument); resultDocument.save('whatever.xml'); } }

While I tested I have seen that the transformtion is not quite doing what you want as you also seem to want to remove any "prefixes" in attribute values so you need to change the stylesheet to use the following template for attribute nodes:

<xsl:template match="@*">
<xsl:attribute name="{local-name}">
<xsl:choose>
<xsl:when test="contains(., ':')">
<xsl:value-of select="substring-after(., ':')" />
</xsl:when>
<xsl:eek:therwise>
<xsl:value-of select="." />
</xsl:eek:therwise>
</xsl:choose>
</xsl:attribute>
</xsl:template>
 

Matt Muise

Usenet Archive
Joined
Apr 8, 2004
Messages
3
Reaction score
0
Hi there, I have one more question about this.

If I have a document like ...

<ROOT>
<ITEMS>
<ITEM>
<DATA>01234567</DATA>
<NAME>Name1</NAME>
</ITEM>
<ITEM>
<DATA>76543210</DATA>
<NAME>Name2</NAME>
</ITEM>
</ITEMS>
</ROOT>

... how would I add the value of the NAME node as an attribute of the DATA node ... for example ...

<ROOT>
<ITEMS>
<ITEM>
<DATA name="Name1">01234567</DATA>
</ITEM>
<ITEM>
<DATA name="Name2">76543210</DATA>
</ITEM>
</ITEMS>
</ROOT>

Sorry for my non understanding of XSL.

Matt
 

Alex Shirshov

Usenet Archive
Joined
Feb 25, 2004
Messages
19
Reaction score
0
Hello, Matt!
You wrote on 12 Apr 2004 17:17:31 GMT:

[Sorry, skipped]

[xslt]
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:eek:utput method="xml" version="1.0" encoding="UTF-8" indent="yes"/> <xsl:template match="@*|node"> <xsl:copy> <xsl:apply-templates select="@* | node"/> </xsl:copy> </xsl:template>

<xsl:template match="ITEM">
<ITEM>
<DATA name="{NAME}">
<xsl:value-of select="DATA"/>
</DATA>
</ITEM>
</xsl:template>
</xsl:stylesheet>
[/xslt]

With best regards, Alex Shirshov.
 

Matt Muise

Usenet Archive
Joined
Apr 8, 2004
Messages
3
Reaction score
0
Cool ... that does work, except for one problem. The DATA node has several subnodes underneath it which get lost when the transform takes place. I probably should have mentioned the fact that there are subnodes underneath, eh?

So the document is more like:

<ROOT>
<ITEMS>
<ITEM>
<DATA>
<THIS>121212</THIS>
<THAT>121212</THAT>
</DATA>
<NAME>name1</name>
</ITEM>
<ITEM>
<DATA>
<ONE>121212</ONE>
<TWO>121212</TWO>
</DATA>
<NAME>name2</name>
</ITEM>
</ITEMS>
</ROOT>

I want to preserve all the nodes underneath data. Data can contain several different types of nodes. Sorry I didn't mention this in the initial posting.

Thanks for your assistance!

Matt
 

Alex Shirshov

Usenet Archive
Joined
Feb 25, 2004
Messages
19
Reaction score
0
Hello, Matt!
You wrote on 13 Apr 2004 12:57:24 GMT:

[Sorry, skipped]

Oh, it's simple.
Replace the
[xslt]
<DATA name="{NAME}">
<xsl:value-of select="DATA"/>
</DATA>
[/xslt]
on
[xslt]
<DATA name="{NAME}">
<xsl:apply-templates select="*[not(self::NAME)]"/>
</DATA>

[/xslt]

With best regards, Alex Shirshov.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
548,208
Messages
3,104,799
Members
249,594
Latest member
henrywalsh

Latest Threads

Top