Clinton Pierce
Clinton Pierce

Reputation: 13189

XmlReader to return node as-is without children

I'm traversing a large XML document using XmlReader and stitching it into a much smaller and more manageable XmlDocmuent. Along the way, I find a node that's interesting so to move it I do this:

        targetDoc.LoadXml("<result></result>");
        // Some interesting code removed
        using (XmlReader r = XmlReader.Create(file))
        {
            while (r.Read())
            {
                if (r.NodeType == XmlNodeType.Element)
                {
                    if (r.Name == match)
                    {
                        // Put the node into the target document
                        targetDoc.FirstChild.InnerXml = r.ReadOuterXml();
                        return targetDoc;
                    }
                }
             }
         }

This is all well and good, except I'd like to include the node without its descendents. What I'm interested in is the node itself with its attributes. The descendents are very large, bulky and uninteresting at this point. (And reading them into memory all at once will cause out of memory errors...)

Is there an easy way to get the text (?) of the found element with its attributes -- but not its descendents -- into the target document?

Upvotes: 0

Views: 1453

Answers (3)

Conrad Frix
Conrad Frix

Reputation: 52675

I don't think there's a Built-in way of doing it. I think you have to read out the Attributes and content yourself.

e.g.

static void Main(string[] args)
        {
            var xml = @"<root>
                                <parent a1 = 'foo' a2 = 'bar'>Some Parent text
                                    <child a3 = 'frob' a2= 'brob'> Some Child Text
                                    </child>
                                </parent>
            </root>";
            var file = new StringReader(xml) ;

            using (XmlReader r = XmlReader.Create(file))
            {
                while (r.Read())
                {
                    if (r.NodeType == XmlNodeType.Element)
                    {
                        if (r.Name == "parent")
                        {
                            var output = new StringBuilder();
                            var settings = new XmlWriterSettings();
                            settings.OmitXmlDeclaration = true;
                            using (var elementWriter = XmlWriter.Create(output, settings))
                            {   

                                elementWriter.WriteStartElement(r.Name);

                                elementWriter.WriteAttributes(r,false);
                                elementWriter.WriteValue(r.ReadString());
                                elementWriter.WriteEndElement();
                            }

                            Console.WriteLine(output.ToString());
                        }
                    }
                }
            }


            if (System.Diagnostics.Debugger.IsAttached)
                Console.ReadLine();

        }

Will produce

<parent a1="foo" a2="bar">Some Parent text</parent>
Press any key to continue . . .

Upvotes: 1

Kyle W
Kyle W

Reputation: 3752

Not necessarily a great way, but you can read the string until you get to the end of the start tag, and then manually append an end tag and load that into an XmlDocument.

edit:

Thinking something like:

string xml = r.ReadOuterXml();
int firstEndTag = xml.IndexOf('>');
int lastStartTag = xml.LastIndexOf('<');
string newXml = xml.Substring(0, firstEndTag) + xml.Substring(lastStartTag);

This might not be valid at all, given that there's a large string right there. Your way might be the best. Neither are pretty, but I personally can't think of a better way, given your constraints (which is not to say that a better way doesn't exist).

Upvotes: 0

slobodans
slobodans

Reputation: 859

You can try XmlNode.CloneNode(bool deep) method.

deep: true to recursively clone the subtree under the specified node; false to clone only the node itself.

Upvotes: 0

Related Questions