XmlReader按原样返回节点而没有子节点

时间:2011-09-15 17:25:21

标签: c# xml xmlreader

我正在使用XmlReader遍历一个大型XML文档,并将其拼接成更小,更易于管理的XmlDocmuent。一路上,我发现一个有趣的节点,所以移动它我这样做:

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

这一切都很好,除了我想要包含节点而没有它的后代。我感兴趣的是节点本身及其属性。在这一点上,后代非常庞大,笨重且无趣。 (并将它们一次性读入内存会导致内存不足错误......)

是否有一种简单的方法可以将找到的元素的文本(?)及其属性(而不是其后代)放入目标文档中?

3 个答案:

答案 0 :(得分:1)

我认为没有内置的方法。我想你必须自己读出属性和内容。

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();

        }

将产生

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

答案 1 :(得分:0)

您可以尝试使用XmlNode.CloneNode(bool deep)方法。

deep:true以递归方式克隆指定节点下的子树; false仅克隆节点本身。

答案 2 :(得分:0)

不一定很好,但是你可以读取字符串,直到你到达开始标记的末尾,然后手动附加一个结束标记并将其加载到XmlDocument中。

编辑:

思考如下:

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

这可能根本没有效果,因为那里有一个大字符串。你的方式可能是最好的。两者都不漂亮,但考虑到你的限制(这并不是说更好的方法不存在),我个人想不出更好的方法。