简体   繁体   English

如何在C#中读写XML文件而不依赖标签名称?

[英]how to read & write xml file in C# not rely on the tag name?

Thank you very much for reading my question. 非常感谢您阅读我的问题。

the bottom is the sample of my xml file.please refer that. 底部是我的xml文件的示例。请参考。

i did some xml files before, but by "CMarkXml". 我之前做了一些xml文件,但是通过“ CMarkXml”。 "IntoElement, OutofElement", is very clear. “ IntoElement,OutofElement”非常清楚。

but when C#...i was lost.. 但是当C#...我迷路了..

1: how to read & write my xml file without using the tag name. 1:如何在不使用标签名称的情况下读写我的xml文件。 i see some articles about operation on xml file by c#, but all assumed that known the tag name. 我看到了一些有关C#对xml文件进行操作的文章,但所有文章都假定知道标签名称。

2: if without tag name, it is very difficult or not recommend. 2:如果没有标签名称,则很难或不推荐。 then how to read & write my xml file by XmlDocument? 那么如何通过XmlDocument读写我的xml文件? (sorry, but no Ling please, i am very faint with that...). (对不起,请不用玲,我对此感到非常晕眩...)。

3: my idear is, for the xml file, get out some section, we still could parse the section by xmldocument. 3:我的想法是,对于xml文件,删除一些部分,我们仍然可以通过xmldocument来解析该部分。

4: for the write/modify the xml file, of course, should contain delete some section, delete some "leaf", change the attributes... 4:对于写/修改xml文件,当然应该包含删除一些部分,删除一些“叶子”,更改属性...

Thank you very much for reading the long question, and any help i will very appreciate. 非常感谢您阅读长期的问题,我将不胜感激。 If you have a good sample code but not continent paste them here, could you send it to "erlvde@gmail.com"? 如果您有一个好的示例代码,但没有大洲将其粘贴到此处,可以将其发送到“ erlvde@gmail.com”吗?

<root>
    <a>i belong to a</a>
    <b>
        <bb>
            <bb>1</bb>
            <bb>2</bb>
            <bb>3</bb>
            <bb>4</bb>
            <bb>5</bb>
        </bb>
        <bb>
            <bb>1</bb>
            <bb>2</bb>
            <bb>3</bb>
            <bb>4</bb>
            <bb>5</bb>
        <bb>
    ....(other <bb>)
    </b>
</root>

Read your xml into XmlDocument : 将您的xml读入XmlDocument

var xmlDocument = new XmlDocument();
xmlDocument.LoadXml("XML HERE");

Access child nodes: 访问子节点:

xmlDocument.ChildNodes[1]

But it's also true that it's very error prone 但是也很容易出错

You can also check if you have child nodes at all: 您还可以检查是否有子节点:

xmlDocument.HasChildNodes

And get number of child nodes: 并获得子节点数:

xmlDocument.ChildNodes.Count

It looks to me like your elements names contain identifiers. 在我看来,您的元素名称包含标识符。 If that is the case, and you have control over the XML schema, I would highly recommend changing your XML to contain elements and/or attributes indicating your identifiers and then use the built in XmlSerializer class for serializing to and from XML. 如果是这种情况,并且您可以控制XML模式,则强烈建议您更改XML以使其包含表示标识符的元素和/或属性,然后使用内置的XmlSerializer类来与XML进行串行化。 It has many modifiers available, such as XmlElement and XmlAttribute among many others, for formatting the output. 它具有许多可用的修饰符,例如XmlElementXmlAttribute ,可用于格式化输出。

Here is a tutorial to get you started. 是一个入门指南。

If possible, change your XML to something like following which would make it far simpler to manipulate...again if changing the schema is a possibility. 如果可能的话,将您的XML更改为如下所示,这将使操作变得更加简单...同样,如果有可能更改架构,则也是如此。

<root>
    <a>i belong to a</a>
    <b>
        <bb id="1">
            <bb>1</bb>
            <bb>2</bb>
            <bb>3</bb>
            <bb>4</bb>
            <bb>5</bb>
        </bb>
        <bb id="2">
            <bb>1</bb>
            <bb>2</bb>
            <bb>3</bb>
            <bb>4</bb>
            <bb>5</bb>
        <bb>
    </b>
</root>

Edit this edit reflects the changes you made to your XML 编辑 此编辑内容将反映您对XML所做的更改


Here is a simple console application which will serialize an object to an XML file and then rehydrate it. 这是一个简单的控制台应用程序,它将将对象序列化为XML文件,然后对其进行重新水化处理。

Expected XML 预期的XML

<?xml version="1.0" encoding="utf-8"?>
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <a>i belong to a</a>
  <b>
    <bb>
      <bb>1</bb>
      <bb>2</bb>
      <bb>3</bb>
      <bb>4</bb>
      <bb>5</bb>
    </bb>
    <bb>
      <bb>1</bb>
      <bb>2</bb>
      <bb>3</bb>
      <bb>4</bb>
      <bb>5</bb>
    </bb>
  </b>
</root>

Simple Console Application Demonstration 简单控制台应用程序演示

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.IO;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var items = new root
            {
                a = "i belong to a",
                b = new List<bb>
                {
                    new bb
                    {
                        bbClassProperty = new List<int>
                        {
                            1,
                            2,
                            3,
                            4,
                            5
                        }
                    },
                    new bb
                    {
                        bbClassProperty= new List<int>
                        {
                            1,
                            2,
                            3,
                            4,
                            5
                        }
                    }
                }
            };

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

            using (var textWriter = new StreamWriter(@"C:\root.xml"))
            {
                serializer.Serialize(textWriter, items);
                textWriter.Close();
            }

            using (var stream = new StreamReader(@"C:\root.xml"))
            {
                var yourObject = serializer.Deserialize(stream);
            }

            Console.Read();
        }
    }

    #region [Classes]

    public class root
    {
        public string a { get; set; }

        public List<bb> b { get; set; }
    }

    public class bb
    {
        [XmlElement("bb")]
        public List<int> bbClassProperty { get; set; }
    }

    #endregion
}

Look into the ChildNodes (and similar) properties and methods on your XmlElement object. 查看XmlElement对象上的ChildNodes (和类似的)属性和方法。 These will let you iterate over the children of a node and you can then ask that node for its name. 这些将使您可以遍历节点的子代,然后可以要求该节点提供其名称。

If you have a XmlNode object, you can use XMLNode.FirstChild to get the child, if it has any. 如果您有XmlNode对象,则可以使用XMLNode.FirstChild获取该子对象(如果有)。 You can also use XMLNode.NextSibling to get the next Node of the same parent node. 您还可以使用XMLNode.NextSibling获取同一父节点的下一个Node。 Why can't you use the names of the nodes? 为什么不能使用节点名称? It's the easiest and most common way. 这是最简单,最常见的方式。 Especially if you use XPath or similar. 特别是如果您使用XPath或类似的东西。

XPath is also the answer to your second question. XPath也是第二个问题的答案。

U can use the class XML reader, a simple example is given here . U可以使用XML阅读器类, 这里给出一个简单的示例。

using System;
using System.Xml;

class Program
{
    static void Main()
    {
    // Create an XML reader for this file.
    using (XmlReader reader = XmlReader.Create("perls.xml"))
    {
        while (reader.Read())
        {
        // Only detect start elements.
        if (reader.IsStartElement())
        {
            // Get element name and switch on it.
            switch (reader.Name)
            {
            case "perls":
                // Detect this element.
                Console.WriteLine("Start <perls> element.");
                break;
            case "article":
                // Detect this article element.
                Console.WriteLine("Start <article> element.");
                // Search for the attribute name on this current node.
                string attribute = reader["name"];
                if (attribute != null)
                {
                Console.WriteLine("  Has attribute name: " + attribute);
                }
                // Next read will contain text.
                if (reader.Read())
                {
                Console.WriteLine("  Text node: " + reader.Value.Trim());
                }
                break;
            }
        }
        }
    }
    }
}

The input file text is: 输入文件的文本为:

<?xml version="1.0" encoding="utf-8" ?>
<perls>
    <article name="backgroundworker">
    Example text.
    </article>
    <article name="threadpool">
    More text.
    </article>
    <article></article>
    <article>Final text.</article>
</perls>

Output 输出量

Start element. 起始元素。

Start element. 起始元素。

Has attribute name: backgroundworker 具有属性名称:backgroundworker

Text node: Example text. 文本节点:示例文本。

Start element. 起始元素。

Has attribute name: threadpool 具有属性名称:threadpool

Text node: More text. 文本节点:更多文本。

Start element. 起始元素。

Text node: 文字节点:

Start element. 起始元素。

Text node: Final text. 文本节点:最终文本。 enter code here

You can use the following code to if the file does not contain the headers, in the example above. 在上面的示例中,如果文件不包含标题,则可以使用以下代码。

XmlReaderSettings settings = new XmlReaderSettings();
                settings.ConformanceLevel = ConformanceLevel.Fragment;
reader = XmlReader.Create(filePath, settings)

Would something like this help? 这样的帮助吗?

void Iterate(XmlNode parent) {
    //do something with
    //parent.Name
    //parent.Value
    //parent.Attributes

    foreach(XmlNode child in parent.ChildNodes) {
        Iterate(child);
    }
}

XmlDocument document = new XmlDocument();
document.Load(filename);

XmlNode parent = document.DocumentElement;
Iterate(parent);

You could also store it like that (sorry for any syntactical error, didn't run it) 您也可以这样存储它(对不起任何语法错误,没有运行它)

public class Document {
    public Element DocumentElement { set; get; }

    private void Load(string fileName) {
        XmlDocument document = new XmlDocument();
        document.Load(fileName);

        DocumentElement = new Element(this, null);
        DocumentElement.Load(document.DocumentElement);
    }
}

public class Element {
    public string Name { set; get; }
    public string Value { set; get; }
    //other attributes

    private Document document = null;
    private Element parent = null;
    public Element Parent { get { return parent; } }
    public List<Element> Children { set; get; }
    private int order = 0;

    public Element(Document document, Element parent) {
        Name = "";
        Value = "";
        Children = new List<LayoutElement>();

        this.document = document;
        this.parent = parent;
        order = parent != null ? parent.Children.Count + 1 : 1;
    }

    private Element GetSibling(bool left) {
        if(parent == null) return null;
        int add = left ? -1 : +1;
        Element sibling = parent.Children.Find(child => child.order == order + add);
        return sibling;
    }

    public Element GetLeftSibling() {
        return GetSibling(true);
    }

    public Element GetRightSibling() {
        return GetSibling(false);
    }

    public void Load(XmlNode node) {
        Name = node.Name;
        Value = node.Value;
        //other attributes

        foreach(XmlNode nodeChild in node.Children) {
            Element child = new Element(document, this);
            child.Load(nodeChild);
            Children.Add(child);
        }
    }
}

Document document = new Document();
document.Load(fileName);

For changing/deleting right now you could iterate the tree and find elements by name, but since name is not unique, you would affect many elements at once. 为了立即更改/删除,您可以遍历树并按名称查找元素,但是由于名称不是唯一的,因此您会同时影响许多元素。 You could add an unique id in every tag like 您可以在每个标签中添加唯一的ID,例如

<bb id="bb1"/>

Then read it in Load function like 然后像读取功能一样读取它

id = ((XmlElement)node).GetAttribute("id");

and use this id to iterate through the tree. 并使用此ID遍历树。 Sorry I don't have time right now to provide something more detailed. 抱歉,我现在没有时间提供更详细的信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM