我现在做一个 将数据库中的 线性 数据记录列表 转换为xml 格式的层次结构字符串,在运行的时候,报 xnav 的所有属性异常,能帮忙看下错误在什么地方。 代码如下:
XmlDocument xdoc = new XmlDocument();
        xdoc.LoadXml("<menu></menu>");
        XPathNavigator xnav = xdoc.CreateNavigator();
        SqlProcedure sp = new SqlProcedure("get_types_brands_series");
        SqlResult rs = sp.CallNoParam();
        DataTable dt = rs.dataSet.Tables[0];
        int rowsnum = dt.Rows.Count;        for (int xh = 0; xh <= rowsnum; xh++)
        {
            xnav.MoveToChild();    //--出错时,调试中发现,这里就已经出现 xnav 的很多属性有异常
            DataRow row = dt.Rows[xh];
            string tidstr = "T" + row["tid"].ToString();
            string bidstr = "B" + row["bid"].ToString();
            string sidstr = "S" + row["sid"].ToString();           if (xnav.SelectSingleNode("/menu/" + tidstr).IsNode) //《---运行时 这里报错 
            {
                xnav.MoveToChild(tidstr, "");
                if (xnav.SelectSingleNode("/menu/" + tidstr + "/" + bidstr).Name != String.Empty)
                {
                    xnav.MoveToChild(bidstr, "");
                    if (xnav.SelectSingleNode("/menu/" + tidstr + "/" + bidstr + "/" + sidstr).Name == String.Empty)
                    {
                        xnav.AppendChild("<" + sidstr + ">" + row["sname"].ToString() + "</" + sidstr + ">");                    }
                }
                else
                {
                    //xnav.MoveToChild(row["tid"].ToString(),"");
                    xnav.AppendChild("<" + bidstr + " sname=" + row["bname"].ToString() + "></" + bidstr + ">");                }
            }
            else
            {
                //xnav.MoveToRoot();
                xnav.AppendChild("<" + tidstr + "></" + tidstr + ">");
            }        }
     
        return xdoc.InnerXml;

解决方案 »

  1.   

     xnav.MoveToChild();  
    这个可以编译过去么???
    这个方法得带参数吧???
    搞不清楚你的数据结构是什么样的
    参考下如下代码
    使用XmlElement和XmlAttribute实现~~XmlDocument xdoc = new XmlDocument();
    xdoc.LoadXml("<menu></menu>");
    SqlProcedure sp = new SqlProcedure("get_types_brands_series"); 
    SqlResult rs = sp.CallNoParam(); 
    DataTable dt = rs.dataSet.Tables[0]; 
    int rowsnum = dt.Rows.Count;for (int xh = 0; xh < rowsnum; xh++)
    {
        DataRow row = dt.Rows[xh];
        string tidstr = "T" + row["tid"].ToString();
        string bidstr = "B" + row["bid"].ToString();
        string sidstr = "S" + row["sid"].ToString();    if (xdoc.SelectSingleNode(String.Format("/menu/{0}", tidstr)) != null)
        {
            if (xdoc.SelectSingleNode(String.Format("/menu/{0}/{1}", tidstr, bidstr)) != null)
            {
                if (xdoc.SelectSingleNode(String.Format("/menu/{0}/{1}/{2}", tidstr, bidstr, sidstr)) == null)
                {
                    XmlElement xe = xdoc.CreateElement(sidstr);
                    xe.InnerText = row["sname"].ToString();
                    xdoc.AppendChild(xe);
                }
            }
            else
            {
                XmlElement xe = xdoc.CreateElement(bidstr);
                XmlAttribute xa = xdoc.CreateAttribute("sname");
                xa.Value = row["bname"].ToString();
                xe.Attributes.Append(xa);
                xdoc.AppendChild(xe);
            }
        }
        else
        {
            XmlElement xe = xdoc.CreateElement(tidstr);
            xdoc.AppendChild(xe);
        }
    }
    return xdoc.InnerXml;
      

  2.   

    你要注意的是SelectSingleNode方法如果没有查询到数据他是返回null的
    所以不能直接使用IsNode或者Name等属性~~~
    另外你要注意的是XPathNavigator执行了Move后,他所指向的Node是否是你需要的Node
      

  3.   

    没错,上面的程序写错了,MoveToChild()应该是 MoveToRoot();
    我的数据结构是这样的 : 
    tid   bid   bname   sid   sname
    0     100   b1      1000  s1
    0     100   b1      1001  s2
    0     100   b1      1002  s3
    0     100   b1      1003  s4
    0     100   b1      1004  s5
    0     101   b2      1005  s6
    0     101   b2      1006  s7
    1     102   b3      1007  s8
    1     102   b3      1008  s9
    1     103   b4      1009  s10
    ..................
    最后要变成 
    <menu>
      <T0>
        <B100 bname="b1">
          <S1000>s1</S1000>
          <S1001>s2</S1001>
          <S1002>s3</S1002>
          <S1003>s4</S1003>
          <S1004>s5</S1004>
        </B100>
        <B101 bname="b2">
          <S1005>s6</S1005>
          <S1006>s7</S1006>
        </B101>
      </T0>
      <T1>
        <B102 bname="b3">
          <S1007>s8</S1007>
          <S1008>s9</S1008>
        </B102>
        <B103 bname="b4">
          <S1009>s10</S1000>
          .......
        </B103>
        ....
      </T1>
      ......
    </menu>
    想用XmlDocument 结合 XPathVavigator 来进行转换。 
      

  4.   

    你非得要用XPathNavigator的话,那就应该先去看看MSDN关于XPathNavigator的解释~~~~你的功能参照下面代码
    XmlDocument xdoc = new XmlDocument();
    xdoc.LoadXml("<menu></menu>");
    XPathNavigator xnav = xdoc.CreateNavigator();
    SqlProcedure sp = new SqlProcedure("get_types_brands_series"); 
    SqlResult rs = sp.CallNoParam(); 
    DataTable dt = rs.dataSet.Tables[0];
    foreach (DataRow row in dt.Rows)
    {
        xnav.MoveToRoot();
        xnav.MoveToChild("menu", "");
        string tidstr = "T" + row["tid"].ToString();
        string bidstr = "B" + row["bid"].ToString();
        string sidstr = "S" + row["sid"].ToString();    if (xnav.SelectSingleNode("/menu/" + tidstr) == null)
        {
            xnav.AppendChild(String.Format("<{0}></{0}>", tidstr));
        }
        xnav.MoveToChild(tidstr, "");
        if (xnav.SelectSingleNode(String.Format("/menu/{0}/{1}", tidstr, bidstr)) == null)
        {
            xnav.AppendChild(String.Format("<{0} bname=\"{1}\"></{0}>", bidstr, row["bname"].ToString()));
        }    xnav.MoveToChild(bidstr, "");
        if (xnav.SelectSingleNode(String.Format("/menu/{0}/{1}/{2}", tidstr, bidstr, sidstr)) == null)
        {
            xnav.AppendChild(String.Format("<{0}>{1}</{0}>", sidstr, row["sname"].ToString()));
        }
        else
        {
            //如果sid已经存在的情况,你可以更新使用新的数据,也可以不做处理使用原来的数据,这个就看你的逻辑了
        }
    }
    return xdoc.InnerXml;
      

  5.   

    谢谢lovefootball我在看到你的答案前我也摸出来了,3天的时间,郁闷,还是基本知识不扎实:private string ListToXml()
        {
            XmlDocument xdoc = new XmlDocument();
            xdoc.LoadXml("<menu></menu>");
            XPathNavigator xnav = xdoc.CreateNavigator();
            SqlProcedure sp = new SqlProcedure("get_types_brands_series");
            SqlResult rs = sp.CallNoParam();
            DataTable dt = rs.dataSet.Tables[0];
            int rowsnum = dt.Rows.Count;        for (int xh = 0; xh < rowsnum; xh++)
            {
                DataRow row = dt.Rows[xh];
                string tidstr = "T" + row["tid"].ToString();
                string bidstr = "B" + row["bid"].ToString();
                string sidstr = "S" + row["sid"].ToString();
                string bname = row["bname"].ToString();
                string sname = row["sname"].ToString();            xnav.MoveToRoot();
                xnav.MoveToChild("menu", "");
                if (xnav.SelectSingleNode(String.Format("/menu/{0}", tidstr)) != null)
                {
                    xnav.MoveToChild(tidstr, "");
                    if (xnav.SelectSingleNode(String.Format("/menu/{0}/{1}", tidstr, bidstr)) != null)
                    {
                        xnav.MoveToChild(bidstr, "");
                        if (xnav.SelectSingleNode(String.Format("/menu/{0}/{1}/{2}", tidstr, bidstr, sidstr)) == null)
                        {
                            xnav.AppendChild(String.Format("<{0}>{1}</{0}>", sidstr, sname));
                        }
                    }
                    else
                    {
                        xnav.AppendChild(String.Format("<{0} bname=\"{1}\"></{0}>", bidstr, bname));                }
                }
                else
                {
                    xnav.AppendChild(String.Format("<{0}></{0}>", tidstr));
                }        }
                return (xdoc.InnerXml);
            
        }