将数据写入现有 Xml

Writing data to existing Xml

我正在 windows 10 Visual Studio 2015 上开发通用 windows 应用程序,并且有一个相当大的 Xml 结构如下:

<header id = "1">
    <title>
        some text
    </title>
    <question>
        a question
    </question>
    <user_input>
        <input1>
        </input1>
        <input2>
        </input2>
    </user_input>
</header>

<header id = "2">
    <title>
        some text
    </title>
    <question>
        a question
    </question>
    <user_input>
        <input1>
        </input1>
        <input2>
        </input2>
    </user_input>
</header>
...

这重复了很多次。有些部分永远不应更改(例如标题、问题)。现在我想将新元素写入 "ui",以便它可以再次读取并在 texbox 中显示新内容。 我使用 FileStream 和 XmlDocument 以及 XmlNodeList 来读取 Xml 并在文本块上显示内容:

path = "test.xml";
FileStream stream = new Filestream(path, FileMode.Open, FileAcces.Read);
XmlDocument xdoc = new XmlDocument();
xdoc.Load(reader);
XmlNodeList node = xdoc.GetElementsByTagName("header");
textblock1.Text = node[0].Attributes["id"].Value;
textblock2.Text = node[i].ChildNode[1].InnerText;
....

我试过这个写入 Xml:

XDocument xdoc = XDocument.Load(path);
XElement ele = xdoc.Element("header");
ele.Add(new XElement("user_input",
        new XElement("input1", newtext)));
        xdoc.Save(path); <---- at this point there is an error

"Argument 1: cannot convert from 'string' to 'System.IO.Stream'"

我的问题是:如何将用户输入(一些字符串)写入我想要的位置?第一个输入应写入 header with id = 1 到 user_input,第二个输入到 header id = "2" 等等。我已经尝试用 XDocument 加载 xml 并用 XElement 编写一个新元素,但它在 all.Is 工作,我的 xml 有问题吗?还是它的功能?提前谢谢你。

首先,xml 文件不能包含相同的根,这里有两个 headers 节点,但看不到根节点。所以我添加了一个根节点来测试你的xml文件如下

<?xml version="1.0" encoding="utf-8"?>
<Topics>
<header id = "1">
...
</header>
</Topics>

其次,这个错误

"Argument 1: cannot convert from 'string' to 'System.IO.Stream'"

xdoc.save(string)在uwp中是没有的,具体可以看XDocument.Save method的版本信息。

第三,对于这个问题

how can i write the user input (some string) to the place I want it to be?

我们可以通过xpathGetElementsByTagName方法向特殊元素插入值。在 uwp 中,我建议您使用 Windows.Data.Xml.Dom 命名空间而不是 System.xml.Ling.

这里我写了一个插入值到特殊位置的演示。并将demo上传到GitHub,大家可以下载CXml进行测试

主要代码

private async void BtnXmlWrite_Click(object sender, RoutedEventArgs e)
{
    String input1value = TxtInput.Text;
    if (null != input1value && "" != input1value)
    {
        var value = doc.CreateTextNode(input1value);
        //find input1 tag in header where id=1
        var xpath = "//header[@id='1']/user_input/input1";
        var input1nodes = doc.SelectNodes(xpath);
        for (uint index = 0; index < input1nodes.Length; index++)
        {
            input1nodes.Item(index).AppendChild(value);
        }
        RichEditBoxSetMsg(ShowXMLResult, doc.GetXml(), true);    
    }
    else
    {
        await new Windows.UI.Popups.MessageDialog("Please type in content in the  box firstly.").ShowAsync();
    }
}

更多细节你可以参考XML dom Sample, XML and XPath