【问题标题】:Retrieving sub elements of xml using Xdocument使用 Xdocument 检索 xml 的子元素
【发布时间】:2013-12-30 12:59:41
【问题描述】:

我想像这样解析一个 XML 文件:

 <?xml version="1.0" encoding="utf-8" ?> 
    <database name="myDb">
      <table name="myTable">
        <field name="Code" type="int" size="0" identity="true" primarykey="true" description="کد شناسه" reference=""></field>
        <field name="Name" type="nvarchar" size="50" identity="false" primarykey="false" description="نام شخص" reference=""></field>
      </table>
      <table name="yourTable">
        <field name="Code" type="int" size="0" identity="true" primarykey="true" description="کد شناسه" reference=""></field>
        <field name="Title" type="nvarchar" size="50" identity="false" primarykey="false" description="نام شخص" reference=""></field>
      </table>
    </database>

问题在于,在我的内部 foreach 中,它将解析 4 个字段,而不是与每个表相关的 2 个字段。如何将代码更改为只读取当前表的字段?

XDocument xdoc = XDocument.Load("d:\\tables.xml");
        foreach (XNode table in xdoc.Descendants("database").Nodes())
        {
            fields = "";
            tableName = XElement.Parse(table.ToString()).Attribute("name").Value;
            //XElement xE = XElement.Parse(table.ToString());
            //foreach (XElement e in xE.Elements())
            foreach (XNode field in xdoc.Descendants("table").Nodes())
            {
                fieldName = XElement.Parse(field.ToString()).Attribute("name").Value;
                type = XElement.Parse(field.ToString()).Attribute("type").Value;
                size = XElement.Parse(field.ToString()).Attribute("size").Value;
                identity = XElement.Parse(field.ToString()).Attribute("identity").Value;
                primarykey = XElement.Parse(field.ToString()).Attribute("primarykey").Value;
                description = XElement.Parse(field.ToString()).Attribute("description").Value;
                reference = XElement.Parse(field.ToString()).Attribute("reference").Value;

                if (identity == "true") identity = "identity";
                if (primarykey == "true") primarykey = "primary key";

                if (isChar(type))
                {
                    fields += string.Format(fieldCharTemplate, fieldName, type, size);
                }
                else
                {
                    fields += string.Format(fieldNonCharTemplate, fieldName, type, identity,primarykey);
                }
                //var y = x.Element("type");
            }
            sql = string.Format(tableTemplate, tableName, fields);
            Response.Write(sql);
        }

【问题讨论】:

    标签: c# xml xml-parsing linq-to-xml


    【解决方案1】:

    这就是问题所在:

    foreach (XNode field in xdoc.Descendants("table").Nodes())
    

    这是在 all table 元素下寻找 all 节点。你不想这样。

    您已经得到您正在查看的表格为XElement - 所以使用它。它要求您的table 变量是XElement 而不仅仅是XNode,但这就是您真正想要的......这意味着您不必重新解析它来获取表名。我会把你的代码写成:

    foreach (XElement table in xdoc.Root.Elements("table"))
    {
        string tableName = (string) table.Attribute("name");
        StringBuilder fields = new StringBuilder();
        foreach (XElement field in table.Elements("field"))
        {
            string fieldName = (string) field.Attribute("name");
            string type = (string) field.Attribute("type");
            // Consider casting to int instead...
            string size = (string) field.Attribute("size");
            bool identity = (bool) field.Attribute("identity");
            bool primaryKey = (bool) field.Attribute("primarykey");
            string description = (string) field.Attribute("description");
            string reference = (string) field.Attribute("reference");
            // Append to fields here
        }
    }
    

    请注意,当您已经拥有一个元素时,获取属性要简单得多。在绝大多数情况下,您确实不需要执行多个解析操作。另请注意,我如何将bool 转换为primarykeyidentity。同样,这比手动测试字符串更干净。

    【讨论】:

      【解决方案2】:

      这是解析 xml 的正确方法。表和字段是元素,所以把它们作为元素:

         // instead xdoc.Descendants("database").Nodes()
         xdoc.Descendants("table") // returns all table elements
      

      在获取元素或属性值时也使用强制转换。如果找不到节点,它不会抛出异常,如果您需要解析为布尔、整数等,它将简化您的代码:

      XDocument xdoc = XDocument.Load("d:\\tables.xml");
      foreach (XElement table in xdoc.Root.Elements("table"))
      {
          tableName = (string)table.Attribute("name");
      
          foreach (XElement field in table.Elements("field"))
          {
              fieldName = (string)field.Attribute("name");
              type = (string)field.Attribute("type");
              size = (int)field.Attribute("size"); // that will be an integer
              identity = (bool)field.Attribute("identity"); // boolean
              primarykey = (bool)field.Attribute("primarykey"); // boolean
              description = (string)field.Attribute("description");
              reference = (string)field.Attribute("reference");
              // ...
          }
      
      }
      

      建议大家阅读Querying XML Trees的文章。

      【讨论】:

        【解决方案3】:

        使用 XElement 代替 XNode。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-10-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多