【问题标题】:Append an XML element list附加 XML 元素列表
【发布时间】:2013-05-31 17:52:50
【问题描述】:

我正在尝试重新格式化我的 XML 代码以使其更易于阅读。目前它看起来像这样:

 <Settings>
  <Display_Settings>
    <ScreenName Name="1">1</ScreenName>
    <ScreenTag Tag="1">1</ScreenTag>
    <LocalPosition X="1" Y="1" Z="1">0.000, 0.000, 0.000</LocalPosition>
    <Width Width="0.000">0.000</Width>
    <Height Height="0.000">0.000</Height>
  </Display_Settings>
</Settings>

但是我想要的样子是这样的:

 <Settings>
      <Display_Settings>
        <ScreenName Name="1">1
                 <ScreenTag Tag="1">1</ScreenTag>
                 <LocalPosition X="1" Y="1" Z="1">0.000, 0.000, 0.000</LocalPosition>
                 <Width Width="0.000">0.000</Width>
                 <Height Height="0.000">0.000</Height>
        </ScreenName>
      </Display_Settings>
 </Settings>

好吧,垃圾例子,但我希望你能明白;我希望我的所有值(例如标签和本地位置等)都是屏幕名称的子项。现在我知道要做到这一点,通常是以下调用:

 XmlNode _rootNode; // in the above i'll have set this to be Display_Settings
 _rootNode.AppendChild(_screenTag);

但是,我已将我的 XML 创建代码设置在一个列表中,该列表保存在一个类中并填充到另一个类中。它看起来像这样:

生成 XML

  public HV_WriteXML()
    {
        //root node
        _rootNode = _xmlDoc.CreateElement("InMo_Settings");
        _xmlDoc.AppendChild(_rootNode);

        _userNode = _xmlDoc.CreateElement("Display_Settings");
        _rootNode.AppendChild(_userNode);
    }

    public void GenereateSettingsFile(List<Node> nodeList, string filePath)
    {

        _rootNode.RemoveChild(_userNode);

        _userNode = _xmlDoc.CreateElement("Display_Settings");
        _rootNode.AppendChild(_userNode);

        foreach (Node n in nodeList)
        {
            foreach (XmlElement e in n.GenerateXML(_xmlDoc))
            {
                _userNode.AppendChild(e);
            }
        }
        _xmlDoc.Save(filePath);
    }

然后为了填写这个,我在派生类中执行以下操作:

  public override List<XmlElement> GenerateXML(XmlDocument _xmlDoc)
    {
        List<XmlElement> elementList = new List<XmlElement>();



         if (nodeDictionary.ContainsKey("Name "))
         {
            XmlElement _screenName = _xmlDoc.CreateElement("ScreenName");
            _screenName.SetAttribute("Name", (string)nodeDictionary["Name "].value);
            _screenName.InnerText = (string)nodeDictionary["Name "].value;
            elementList.Add(_screenName);
         }

        if (nodeDictionary.ContainsKey("Tag"))
        {
            XmlElement _screenTag = _xmlDoc.CreateElement("ScreenTag");
            _screenTag.SetAttribute("Tag", (string)nodeDictionary["Tag"].value);
            _screenTag.InnerText = (string)nodeDictionary["Tag"].value;

            elementList.Add(_screenTag);
        }

}

现在我真正的问题是,当我在不同类的列表中设置我的 xml 的创建时,如何附加我的 _screenTag 元素,以便它成为我的屏幕名称的子元素?

【问题讨论】:

  • 你期望的xml包含两次&lt;ScreenName Name="1"&gt;1&lt;/ScreenName&gt;
  • 是的,我手动死记硬背以显示我要完成的工作。感谢您指出这一点。
  • 现在ScreenName 有两个结束标签
  • 更新了您的 xml,使其成为有效的 xml。

标签: c# xml


【解决方案1】:

在我看来,您遇到的困难是您的 c# 数据结构和所需的 XML 数据结构之间的架构不匹配。

即您的列表是一个“平面”结构,但所需的 XML 具有嵌套。

理想情况下,您应该重构您的代码,使两者更相似,您可以为 Display_Settings 创建一个 c# 模型对象,然后根据需要将子属性添加到该类。这可能允许您使用 .Net 内置的 XML 序列化,而不必像现在这样手动启动它。

或者,如果您坚持手动创建 XML,您可以使用 XmlElement 类中对树结构的固有支持,即使用 ChildNodes 属性:http://msdn.microsoft.com/en-us/library/system.xml.xmlnode.childnodes.aspx

【讨论】:

    【解决方案2】:

    您可以通过以下方式在 XML 中的任意位置插入所需的标签,

    //Get Display_Settings node
    XmlNode displaySettingsNode = xmlDoc.SelectSingleNode(@"Settings/Display_Settings");
    //Get LocalPosition node
    XmlNode screenNameNode = xmlDoc.SelectSingleNode(@"Settings/Display_Settings/LocalPosition");
    //Create Screen Tag
    XmlElement screenTag = xmlDoc.CreateElement("ScreenTag");
    screenTag.SetAttribute("Tag", (string)nodeDictionary["Tag"].value);
    screenTag.InnerText = (string)nodeDictionary["Tag"].value;
    //Insert Screen Tag node in desired location
    displaySettingsNode.InsertBefore(screenTag, screenNameNode);
    

    【讨论】:

      【解决方案3】:

      这个怎么样? (使用 LinqToXml)

      var xDoc = XDocument.Parse(xmlstring); //or XDocument.Load(filename)
      
      var elems = xDoc.Descendants("Display_Settings")
                      .First()
                      .Elements()
                      .Where(e => e.Name.LocalName != "ScreenName")
                      .ToList();
      
      elems.ForEach(e => e.Remove());
      
      xDoc.Descendants("ScreenName").First().Add(elems);
      
      var newxml = xDoc.ToString();
      

      【讨论】:

      • @N0xus 这是使用 LinqToXml 的全新代码。 newxml 是你想要的 xml。试试看怎么样?
      猜你喜欢
      • 1970-01-01
      • 2021-04-30
      • 1970-01-01
      • 2017-06-23
      • 2011-10-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多