removing namespaces from an XML document

Discussion in 'XML' started by Matt, Apr 7, 2004.

  1. Matt

    Matt Guest

    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
     
    Matt, Apr 7, 2004
    #1
    1. Advertising

  2. Matt wrote:

    > 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>
    --

    Martin Honnen
    http://JavaScript.FAQTs.com/
     
    Martin Honnen, Apr 8, 2004
    #2
    1. Advertising

  3. Matt

    Matt Muise Guest

    Hey,

    That's awesome!!! It works perfectly!

    Thank you very much!!

    Matt



    *** Sent via Developersdex http://www.developersdex.com ***
    Don't just participate in USENET...get rewarded for it!
     
    Matt Muise, Apr 8, 2004
    #3
  4. Matt

    Matt Muise Guest

    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

    *** Sent via Developersdex http://www.developersdex.com ***
    Don't just participate in USENET...get rewarded for it!
     
    Matt Muise, Apr 12, 2004
    #4
  5. 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.
     
    Alex Shirshov, Apr 13, 2004
    #5
  6. Matt

    Matt Muise Guest

    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

    *** Sent via Developersdex http://www.developersdex.com ***
    Don't just participate in USENET...get rewarded for it!
     
    Matt Muise, Apr 13, 2004
    #6
  7. 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.
     
    Alex Shirshov, Apr 13, 2004
    #7
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. GhislainTanguay
    Replies:
    3
    Views:
    6,311
    Joe Reazor
    May 21, 2004
  2. Tony Prichard
    Replies:
    0
    Views:
    741
    Tony Prichard
    Dec 12, 2003
  3. Manish Hatwalne
    Replies:
    1
    Views:
    401
    Martin Honnen
    Jul 13, 2004
  4. Chris  Chiasson
    Replies:
    6
    Views:
    625
    Richard Tobin
    Nov 14, 2006
  5. Chris Gallagher

    Removing a tag from an xml document

    Chris Gallagher, Nov 24, 2006, in forum: Ruby
    Replies:
    2
    Views:
    131
    Chris Gallagher
    Nov 24, 2006
Loading...

Share This Page