By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
449,277 Members | 1,237 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 449,277 IT Pros & Developers. It's quick & easy.

What is the fastest/efficient way to replace the root element?

P: n/a
Suppose I have an xml fragment like:

<mother>
<child name="Bob" sex="M"/>
<child name="Jane" sex="F"/>
...
</mother>

If I wanted to replace the <mother> element to <father> element, what is the
fastest or most efficient way to do this?

What if I wanted to keep processing instructions, etc. alone that come
before the root?
Or what if I wanted to drop all non-element(root) stuff out?

I am thinking maybe XmlDocument's ReplaceChild?

Thanks very much.
Nov 12 '05 #1
Share this Question
Share on Google+
9 Replies


P: n/a
I realize xsl transform is an option. Let's say other than xsl...

"Jiho Han" <ji******@infinityinfo.com> wrote in message
news:u4**************@TK2MSFTNGP09.phx.gbl...
Suppose I have an xml fragment like:

<mother>
<child name="Bob" sex="M"/>
<child name="Jane" sex="F"/>
...
</mother>

If I wanted to replace the <mother> element to <father> element, what is the fastest or most efficient way to do this?

What if I wanted to keep processing instructions, etc. alone that come
before the root?
Or what if I wanted to drop all non-element(root) stuff out?

I am thinking maybe XmlDocument's ReplaceChild?

Thanks very much.

Nov 12 '05 #2

P: n/a
Jiho Han wrote:
Suppose I have an xml fragment like:

<mother>
<child name="Bob" sex="M"/>
<child name="Jane" sex="F"/>
...
</mother>

If I wanted to replace the <mother> element to <father> element, what is the
fastest or most efficient way to do this?


Basically that depends on your application. In fact the most effective
would be customized XmlReader, which reads mother element as father
element. Here is how it could be done with XmlReaderReader
(http://msdn.microsoft.com/library/de...rcreation.asp).
public class MyXmlReader : XmlReaderReader
{
private bool readingMother;

public MyXmlReader(XmlReader r) : base (r){}

public override String Name
{
get { return base.NodeType == XmlNodeType.Element && readingMother?
"father":base.Name; }
}

public override String LocalName
{
get { return base.NodeType == XmlNodeType.Element &&
readingMother?"father":base.LocalName; }
}

public override bool Read ()
{
bool result;
result = base.Read();

if (base.NodeType == XmlNodeType.Element &&
base.Name == "mother")
readingMother = true;
return result;
}
}

And here is a test:

MyXmlReader r = new MyXmlReader(new XmlTextReader("foo.xml"));
//Test it
XmlDocument doc = new XmlDocument();
doc.Load(r);
doc.Save(Console.Out);
--
Oleg Tkachenko [XML MVP, XmlInsider]
http://blog.tkachenko.com
Nov 12 '05 #3

P: n/a
I see.
Are there other options? Would creating a new element and copying all
attributes and the children be an overkill? I guess it would be for a
sizeable document...
Would xslt perform better than the method above?

Now for a specific case - if I were to employ a derived XmlReader -, let's
say I need to validate the same xml document. The correct root element for
the schema would be <father>, so I would want to replace <mother> with
<father> in my derived XmlReader. I am guessing that XmlValidatingReader
would be wrapped around the derived reader like so:

XmlValidatingReader vReader = new XmlValidatingReader(myXmlReader);

So, when doing:

while(vReader.Read())
{
...
}

The XmlValidatingReader would never even see <mother>, correct?

Lastly, if I were not using a derived Reader, what would I use to
replace/add/remove an element or an attribute on the fly? I say on the fly
because I'm guessing you can always use XmlDocument to manipulate it anyway
you want.

Thanks much.
Jiho

"Oleg Tkachenko [MVP]" <oleg@NO!SPAM!PLEASEtkachenko.com> wrote in message
news:O0****************@tk2msftngp13.phx.gbl...
Jiho Han wrote:
Suppose I have an xml fragment like:

<mother>
<child name="Bob" sex="M"/>
<child name="Jane" sex="F"/>
...
</mother>

If I wanted to replace the <mother> element to <father> element, what is the fastest or most efficient way to do this?
Basically that depends on your application. In fact the most effective
would be customized XmlReader, which reads mother element as father
element. Here is how it could be done with XmlReaderReader

(http://msdn.microsoft.com/library/de...-us/cpguide/ht
ml/cpconcustomizedxmlreadercreation.asp).

public class MyXmlReader : XmlReaderReader
{
private bool readingMother;

public MyXmlReader(XmlReader r) : base (r){}

public override String Name
{
get { return base.NodeType == XmlNodeType.Element && readingMother?
"father":base.Name; }
}

public override String LocalName
{
get { return base.NodeType == XmlNodeType.Element &&
readingMother?"father":base.LocalName; }
}

public override bool Read ()
{
bool result;
result = base.Read();

if (base.NodeType == XmlNodeType.Element &&
base.Name == "mother")
readingMother = true;
return result;
}
}

And here is a test:

MyXmlReader r = new MyXmlReader(new XmlTextReader("foo.xml"));
//Test it
XmlDocument doc = new XmlDocument();
doc.Load(r);
doc.Save(Console.Out);
--
Oleg Tkachenko [XML MVP, XmlInsider]
http://blog.tkachenko.com

Nov 12 '05 #4

P: n/a
Jiho Han wrote:
Are there other options? Lots of!
Would creating a new element and copying all
attributes and the children be an overkill? I guess it would be for a
sizeable document...
Would xslt perform better than the method above? Nope. Loading to DOM and manipulating in-memory is rarely effective. The
same for XSLT - input must be loaded as a whole. Basically what is teh
most eeffective depends on many factors, so the best way is to measure.
The XmlValidatingReader would never even see <mother>, correct?
Sure.
Lastly, if I were not using a derived Reader, what would I use to
replace/add/remove an element or an attribute on the fly? I say on the fly
because I'm guessing you can always use XmlDocument to manipulate it anyway
you want.

I'm not aware of any other "on-the-fly" facility in .NET.
--
Oleg Tkachenko [XML MVP, XmlInsider]
http://blog.tkachenko.com
Nov 12 '05 #5

P: n/a
"Oleg Tkachenko [MVP]" <oleg@NO!SPAM!PLEASEtkachenko.com> wrote in message news:<eT**************@TK2MSFTNGP09.phx.gbl>...
Jiho Han wrote:
Are there other options?

Lots of!
Would creating a new element and copying all
attributes and the children be an overkill? I guess it would be for a
sizeable document...
Would xslt perform better than the method above?

I guess one could also use RegExp. It depends whether it is a file
that needs changing or stream (memory representation (infoset)) or
something else...

Miha
Nov 12 '05 #6

P: n/a
So I created a custom reader deriving from XmlTextReader and overrode three
methods/properties:

Name, LocalName, and Read()

I am feeding this class to XmlSerializer.Deserialize method. I have a class
that was generated by xsd.exe and it is able to serialize/deserialize
properly if I give it a proper Stream or TextReader. It's only when I feed
it my custom XmlReader it fails.
However, if I pipe my custom reader into a writer and save the result to a
string or a stream and feed it back into Deserialize everything is working
again.

The error I get is something like:

There is an error in XML document (1, 2). --->
System.InvalidOperationException: <association_update xmlns=''> was not
expected. at
Microsoft.Xml.Serialization.GeneratedAssembly.XmlS erializationReader1.Read4_
association_update()

which I don't understand what it means. <association> is the original root
and <association_update> is the replacement name my custom reader returns.
I don't know where [xmlns=''] part comes from but even if I create an xml
string by hand with the thing, it works. Upon debugging, it seems that the
XmlSerializationReader is calling CreateUnknownNodeException when it sees
<association_update xmlns=''> node. I tried supplying default namespace
value of "" to the XmlSerializer's constructor and that did not work either.

Was I supposed to override some other property/method in XmlTextReader?
What am I missing?

Thanks for your assistance.
Jiho

"Oleg Tkachenko [MVP]" <oleg@NO!SPAM!PLEASEtkachenko.com> wrote in message
news:eT**************@TK2MSFTNGP09.phx.gbl...
Jiho Han wrote:
Are there other options?

Lots of!
Would creating a new element and copying all
attributes and the children be an overkill? I guess it would be for a
sizeable document...
Would xslt perform better than the method above?

Nope. Loading to DOM and manipulating in-memory is rarely effective. The
same for XSLT - input must be loaded as a whole. Basically what is teh
most eeffective depends on many factors, so the best way is to measure.
The XmlValidatingReader would never even see <mother>, correct?


Sure.
Lastly, if I were not using a derived Reader, what would I use to
replace/add/remove an element or an attribute on the fly? I say on the fly because I'm guessing you can always use XmlDocument to manipulate it anyway you want.

I'm not aware of any other "on-the-fly" facility in .NET.
--
Oleg Tkachenko [XML MVP, XmlInsider]
http://blog.tkachenko.com

Nov 12 '05 #7

P: n/a
Jiho Han wrote:
I am feeding this class to XmlSerializer.Deserialize method. I have a class
that was generated by xsd.exe and it is able to serialize/deserialize
properly if I give it a proper Stream or TextReader. It's only when I feed
it my custom XmlReader it fails.


Well, apparently some namespace issue involved? We've been talking only
about renaming root element on the fly, not about modifying namespace.
The samples you have posted had no namespace.
Without seeing your real XML I can suggest nothing.
--
Oleg Tkachenko [XML MVP, XmlInsider]
http://blog.tkachenko.com
Nov 12 '05 #8

P: n/a
Oleg,

Although I can work around this problem, I'd really like to get to the
bottom of this... as to why this happens. Here is a sample of the incoming
xml:

<?xml version="1.0"?>
<association xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<fromid>8c4a969b-2aa4-4679-b170-d9f6441f7c6d</fromid>
<fromobjecttypecode>1</fromobjecttypecode>
<toid>df3f306f-19de-4f50-9784-623bf6693fa8</toid>
<toobjecttypecode>2</toobjecttypecode>
<forwardrelation>Parent</forwardrelation>
<backrelation>Parent</backrelation>
<forwardnotes>aaa</forwardnotes>
<backnotes>bbb</backnotes>
</association>

My derived XmlReader replaces the association root node to
association_create - simply returning association_create in place of
association in Name and LocalName properties. And here is how I
deserialize:
StringReader sr = new StringReader(Association);

EntityReader er = new EntityReader(sr, "association",
EntityReader.Mode.Create, Context);

XmlSerializer serializer = new XmlSerializer(typeof(association_create));

association_create associationObj = serializer.Deserialize(er) as
association_create;

And below is the class generated by XSD that XmlSerializer uses to
deserialize:

[System.Xml.Serialization.XmlRootAttribute(Namespac e="", IsNullable=false)]

public class association_create {
/// <remarks/>

[System.Xml.Serialization.XmlElementAttribute(Form= System.Xml.Schema.XmlSche
maForm.Unqualified)]

public lookupElement fromid;
/// <remarks/>

[System.Xml.Serialization.XmlElementAttribute(Form= System.Xml.Schema.XmlSche
maForm.Unqualified)]

public int fromobjecttypecode;
/// <remarks/>

[System.Xml.Serialization.XmlElementAttribute(Form= System.Xml.Schema.XmlSche
maForm.Unqualified)]

public lookupElement toid;
/// <remarks/>

[System.Xml.Serialization.XmlElementAttribute(Form= System.Xml.Schema.XmlSche
maForm.Unqualified)]

public int toobjecttypecode;
/// <remarks/>

[System.Xml.Serialization.XmlElementAttribute(Form= System.Xml.Schema.XmlSche
maForm.Unqualified)]

public string forwardrelation;
/// <remarks/>

[System.Xml.Serialization.XmlElementAttribute(Form= System.Xml.Schema.XmlSche
maForm.Unqualified)]

public string backrelation;
/// <remarks/>

[System.Xml.Serialization.XmlElementAttribute(Form= System.Xml.Schema.XmlSche
maForm.Unqualified)]

public string forwardnotes;
/// <remarks/>

[System.Xml.Serialization.XmlElementAttribute(Form= System.Xml.Schema.XmlSche
maForm.Unqualified)]

public string backnotes;

}

I really appreciate your help on this. Thanks.

Jiho
"Oleg Tkachenko [MVP]" <oleg@NO!SPAM!PLEASEtkachenko.com> wrote in message
news:OY**************@TK2MSFTNGP10.phx.gbl...
Jiho Han wrote:
I am feeding this class to XmlSerializer.Deserialize method. I have a class that was generated by xsd.exe and it is able to serialize/deserialize
properly if I give it a proper Stream or TextReader. It's only when I feed it my custom XmlReader it fails.


Well, apparently some namespace issue involved? We've been talking only
about renaming root element on the fly, not about modifying namespace.
The samples you have posted had no namespace.
Without seeing your real XML I can suggest nothing.
--
Oleg Tkachenko [XML MVP, XmlInsider]
http://blog.tkachenko.com

Nov 12 '05 #9

P: n/a
Jiho Han wrote:
Although I can work around this problem, I'd really like to get to the
bottom of this... as to why this happens. Here is a sample of the incoming
xml:


Dunno, works for me. Here is foo.xml file:

<association xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>

The code:
class Class1
{
[STAThread]
static void Main(string[] args)
{
XmlSerializer ser = new XmlSerializer(typeof(association_create));
association_create cr = (association_create)ser.Deserialize(new
MyXmlReader(new XmlTextReader("foo.xml")));
Console.WriteLine(cr);
}
}
[System.Xml.Serialization.XmlRootAttribute(Namespac e="", IsNullable=false)]

public class association_create
{
}

public class MyXmlReader : XmlReaderReader
{
private bool readingAssociation;

public MyXmlReader(XmlReader r) : base (r){}

public override String Name
{
get { return base.NodeType == XmlNodeType.Element &&
readingAssociation? "association_create":base.Name; }
}

public override String LocalName
{
get { return base.NodeType == XmlNodeType.Element &&
readingAssociation?"association_create":base.Local Name; }
}

public override bool Read ()
{
bool result;
result = base.Read();

if (base.NodeType == XmlNodeType.Element &&
base.Name == "association")
readingAssociation = true;
return result;
}

}

--
Oleg Tkachenko [XML MVP, XmlInsider]
http://blog.tkachenko.com
Nov 12 '05 #10

This discussion thread is closed

Replies have been disabled for this discussion.