none
C#修改XML时,xpath显示正常,但每次修改只能修改第一个节点的值!(附Code) RRS feed

  • 问题

  • 我是通过propertyGrid控件来修改XML节点的值的
    private void propertyGridMapFile_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
            {
                try
                {
                    XmlDocument xdoc = new XmlDocument();
                    string xml = GetXmlFileName("mapfile.xml");
                    xdoc.Load(xml);
                    string xpath = "descendant::" + propertyGridMapFile.SelectedGridItem.Label + "[/FileMap/File[FileName='" + picTiff.Tag.ToString () + "']]";
                    //MessageBox.Show(xpath );  显示xpath是我想修改的节点
                    XmlNode node = xdoc.SelectSingleNode(xpath);
                    //MessageBox.Show(xpath +Environment .NewLine + node.ParentNode .InnerXml+Environment .NewLine +picTiff .Tag .ToString () );  显示很正常的
                    node.InnerText = (string)propertyGridMapFile.SelectedGridItem.Value; 这里每次只能修改第一个节点
                    xdoc.Save(xml);
                }
                catch { }
            }

    XML文件:
    <?xml version="1.0"?>
    <FileMap>
      <File>
        <TiffName>000001.tif</TiffName>
        <FileName>E:\新建文件夹\000001.tif</FileName>
        <OriginName>8</OriginName>
       <Comment>ffff</Comment>
        </File>
      <File>
        <TiffName>000002.tif</TiffName>
        <FileName>E:\新建文件夹\000002.tif</FileName>
        <OriginName>4</OriginName>
       <Comment>
        </Comment>
       </File>
      <File>
        <TiffName>000003.tif</TiffName>
        <FileName>E:\新建文件夹\000003.tif</FileName>
        <OriginName>3</OriginName>
        <Comment>
        </Comment>
       </File>
    </FileMap>

    比如我把每个File节点转换为一个类,它的子节点作为属性加载到propertyGrid控件中,我通过properyGrid修改那个Comment节点时,每次都只能修改第一个File的Comment节点,请问这是什么原因,怎么解决?高手给解答一下 谢谢!
    2009年3月19日 12:03

答案

  • 你好!
         当然会这样了,因为那个node本来就是第一个接点啊!你使用SelectNodes方法,然后用foreach遍利这些接点! 

    周雪峰
    2009年3月19日 13:54
    版主
  • 如果XPath显示的结果没有错误,就不是上面代码的问题,上面的代码没有问题。

    XmlNode node = xdoc.SelectSingleNode(xpath);
    node此时只有一个节点,
    node.InnerText = (string)propertyGridMapFile.SelectedGridItem.Value; 这里每次只能修改第一个节点

    node.InnerText设置一个新的值也没有任何问题。

    你需要做的有以下几件事情
    1,检查(string)propertyGridMapFile.SelectedGridItem.Value;的值是否是你期望的,如果不行就写死测试
    node.InnerText = "xxxx";
    2, xdoc.Save(xml);
    之后就去打开mapfile.xml文件看结果,而不是通过其他方法去看
    3.打印出你的xpath的内容是什么,将你的xpath的变量值发来就可以进行测试了
    孟宪会
    2009年3月21日 4:04
    版主

全部回复

  •  XmlNode node = xdoc.SelectSingleNode(xpath);

    这个方法只返回第一个

    请用  xdoc.selectnodes
    热烈庆祝进入4星活跃用户队伍
    有原则的回答问题: 不懂的不去装懂,别人回答得很完整的,没有需要补充的不去蹭分。
    2009年3月19日 12:41
  • 谢谢回复
    但我的意思是我想修改第二个或任意个节点时,xpath显示正确,但最后那个node.InnerText赋值就赋值到了第一个File节点 不管我想修改哪个File节点
    它总是把第一个节点修改了 但xpath指向的那个没有被修改,我每次用propertyGrid修改一个File的子节点

    2009年3月19日 13:13
  • 你好!
         当然会这样了,因为那个node本来就是第一个接点啊!你使用SelectNodes方法,然后用foreach遍利这些接点! 

    周雪峰
    2009年3月19日 13:54
    版主
  •  再次谢谢回复
    但我的问题是我的Xpath明明指向了第二个File节点的Comment,但用node.InnerText赋值后修改的却是第一个File节点的Comment;
    Xpath定位到第三个File节点的Comment,用node.InnerText修改的仍然还是第一个File节点的Comment值
    我纳闷的是为什么 xpath明明定位到了我想修改的值,然后选中这个node,但用node.InnerText却修改了第一个节点的值。
    ◎周雪峰
    我不是要一次把每个节点的Comment都修改了。
    2009年3月20日 14:51
  • 不知道我表达的是不是够清楚了,感兴趣的话 我可以发邮件提供整个 解决方案 源代码!
    可以提供个邮箱我发给你的
    2009年3月20日 15:01
  • 如果XPath显示的结果没有错误,就不是上面代码的问题,上面的代码没有问题。

    XmlNode node = xdoc.SelectSingleNode(xpath);
    node此时只有一个节点,
    node.InnerText = (string)propertyGridMapFile.SelectedGridItem.Value; 这里每次只能修改第一个节点

    node.InnerText设置一个新的值也没有任何问题。

    你需要做的有以下几件事情
    1,检查(string)propertyGridMapFile.SelectedGridItem.Value;的值是否是你期望的,如果不行就写死测试
    node.InnerText = "xxxx";
    2, xdoc.Save(xml);
    之后就去打开mapfile.xml文件看结果,而不是通过其他方法去看
    3.打印出你的xpath的内容是什么,将你的xpath的变量值发来就可以进行测试了
    孟宪会
    2009年3月21日 4:04
    版主
  • 哦,明白你的意思了!
    你先按孟老师的建议检查一下!另外你检查一下
    picTiff.Tag.ToString ()是否是你期望的值!
    周雪峰
    2009年3月21日 6:32
    版主
  •  很高兴继续关注我的问题,谢谢你们提供分析
    关于那个picTiff.Tag.ToString()它是我的MapFile类 构造函数的 参数,是文件的 路径名

    MapFile类的定义

    class MapFile
        {
            public MapFile ()
            {
                ///
            }
            public MapFile(string filename)
            {
                _fileName = filename;
                _tiffName = Path.GetFileName(filename );
                _rename = _tiffName;
            }
            
            public MapFile(XmlNode file)
            {
                _tiffName = file.ChildNodes[0].InnerText ;
                _fileName = file.ChildNodes[1].InnerText;
                _originName = file.ChildNodes[2].InnerText;
                _rename = file.ChildNodes[3].InnerText;
                _type =file.ChildNodes[4].InnerText=="零件"?FileType .零件 :FileType .装配件 ;
                _comment = file.ChildNodes[5].InnerText;
                if (file.ChildNodes[6].ChildNodes.Count > 0)
                {
                    foreach (XmlNode x in file.ChildNodes[6].ChildNodes)
                    {
                       _root.Add(x.ChildNodes [0].InnerText ,x.ChildNodes [1].InnerText  );
                    }
                }
               
            }
            public string _tiffName, _fileName, _originName, _rename,_comment;
            public FileType _type=FileType .零件 ;
            public Hashtable _root = new Hashtable(5);
            public string TiffName
            {
                get
                {
                    return _tiffName;
                }
                set
                {
                    _tiffName = value;
                }
            }

            public string FileName
            {
                get
                {
                    return _fileName ;
                }
            }
            public string OriginName
            {
                get
                {
                    return _originName;
                }
                set
                {
                    _originName = value;
                }
            }
            public string Rename
            {
                get
                {
                    return _rename;
                }
                set
                {
                    _rename = value;
                }
            }
            public enum FileType
            {
                零件=0,
                装配件=1
            }
            public FileType Type
            {
                get
                {
                    return _type;
                }
                set
                {
                    _type = value;
                }
            }
            public Hashtable Root
            {
                get
                {
                    return _root;
                }
            }
            public string Comment
            {
                get
                {
                    return _comment;
                }
                set
                {
                    _comment = value;
                }
            }

    加载PropertyGrid控件时,每次都是通过
    string xpath = "/FileMap/File[FileName='" + node.Tag+ "']";  // 这里的node.Tag来源于TreeView控件的选取项,FromLoad时读取整个            XmlNode xnode = xdoc.SelectSingleNode(xpath);      //  XML文件加载成TreeView,并把每个File节点的FileName设置到TreeNode的Tag中储存
                MapFile mfile = new MapFile(xnode );
                propertyGridMapFile.SelectedObject = mfile;
                picTiff.BackgroundImage = Image.FromFile(mfile .FileName );
                picTiff.Tag =node .Tag ;

    private void propertyGridMapFile_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
            {
                try
                {
                    XmlDocument xdoc = new XmlDocument();
                    string xml = GetXmlFileName("mapfile.ppl");
                    xdoc.Load(xml);
                    string xpath = "descendant::" + propertyGridMapFile.SelectedGridItem.Label + "[/FileMap/File[FileName='" + picTiff.Tag.ToString () + "']]";
                    //MessageBox.Show(xpath );
                    XmlNode node = xdoc.SelectSingleNode(xpath);
                    //MessageBox.Show(xpath +Environment .NewLine + node.ParentNode .InnerXml+Environment .NewLine +picTiff .Tag .ToString () );            //这里打印出的xpath仍然是我想修改的节点位置,但是选取的节点确是第一个,也就是选取了与xpath不符的节点
                 //   node.InnerText = (string)propertyGridMapFile.SelectedGridItem.Value; //这里不会发生异常,值也修改的正确,但就是修改的总是
                                                                                                                                    // 第一个File子节点
                 node.InnexText="xxxx"; (按照孟老师的方法这里直接赋值) 测试中打开了红色的MessageBox.Show()
                                                           //每次修改PropertyGrid的值后,单击Enter提交更改 会弹出对话框 报告 xpath 和 实际选取的 node的值
                xdoc.Save(xml);                 //我这里修改写的是Comment                                                                  
                }
                catch { }
            }

    孟老师你好!
    刚才进行了一下测试 node.InnexText="xxxx"; 保存后打开mapfile.xml(实际 保存成了mapfile.ppl,这个后缀对整个程序没有影响的)查看修改结果
    仍然是修改第一个节点成了"xxxx".       
    用xdoc.SelectSingleNode(xpath) 选取到了与xpath不符的节点是不是一件不可思议的事情啊!
    强烈要求发一份代码给大家帮忙看看错在哪里,整个程序不是很复杂,各位高手花上2分钟就看明白了,我是菜鸟写的程序很简单的,有时间的大哥们留个邮箱我给发一份,也让我这个菜鸟提高一下!
    再次谢谢关注我的问题,也谢谢论坛里其他提出问题和解答问题的人!

    2009年3月21日 14:13
  • 你好!
         你一直显示的都是xpath的值,这本身就是一个字符串,可能看不出问题!
         你把取到的node显示出来看看是不是期望的那个节点! 

    周雪峰
    2009年3月21日 14:36
    版主