【问题标题】:C# Read XML Hierarchy and use FailOver from the parentC# 读取 XML 层次结构并使用父级的故障转移
【发布时间】:2025-12-05 15:40:01
【问题描述】:

我想创建以下 XML。
一个父节点中有多个子节点,父节点包含与子节点相关的节点(作为子节点的默认节点),如果子节点缺少节点,父节点将作为故障转移并为 kis 提供默认节点。

<parents>
   <parent>
      <!--all parent related nodes will be here-->

      <kid-prop>default kid prop</kid-prop><!--this is the default for all kids-->
      <kids>
         <kid>
            <kid-prop>some data</kid-prop>
         </kid>
         <kid></kid><!--since this kid does not have have <kid-prop>, it will be taken from the parent-->
      <kids>
   <parent>
<parents>

如何以编程方式做到这一点很容易,问题是,是否有任何注释方式告诉 xmlreader 父母是孩子的故障转移,以防孩子遗漏一些东西

【问题讨论】:

    标签: c# xml hierarchy xmlreader failover


    【解决方案1】:

    不 - XmlReader 会按原样读取 XML,没有“注释”的概念。如果您使用的是 System.Xml.Linq 而不是 XmlReader,那就很简单了:

    var defaultValue = (string)root.Element("parent").Element("kid-prop");
    root.Element("parent").Element("kids")
    .Elements("kid")
    .Select(kid => 
           kid.Elements("kid-prop").Any() ? 
           (string)kid.Element("kid-prop") : defaultValue);
    

    【讨论】:

      【解决方案2】:

      使用 XmlReader 可以解决需求,但需要大量检查

      下面是示例代码

           using (XmlReader reader = XmlReader.Create(@"D:\Sample.xml"))
              {
      
                  bool b = false;
                  while (reader.Read())
                  {
                      if (reader.NodeType == XmlNodeType.Element)
                      {
      
                          if (reader.Name == "parent")
                          {
                              b = true;
                          }
      
                          if (reader.Name == "kid")
                              b = false;
      
                          if (!b && reader.Name == "kid-prop")
                          {
                              Console.WriteLine(reader.ReadElementContentAsString());
                          }
      
                          if (b && reader.Name == "kid-prop")
                          {
                              Console.WriteLine(reader.ReadElementContentAsString());
                          }
                      }
                  }
              }
      

      否则最好使用linq to xml如下所示

              XElement root = XElement.Load(@"D:\Sample.xml");
      
              var coll = root.Element("parent").Element("kids").Elements("kid").Select(kid => kid.Elements("kid-prop").Any() ? (string)kid.Element("kid-prop") : (string)root.Element("parent").Element("kid-prop"));
      
              foreach (var item in coll)
              {
                  Console.WriteLine(item);
              }
      

      【讨论】: