将控件格式化为xml值

时间:2013-01-17 23:53:41

标签: c# xml winforms linq

我在c#win form中有这个示例代码...

List<string> listFurniture = new List<string>();
XDocument xml = XDocument.Load(Application.StartupPath + @"\Furniture.xml");
foreach (XElement quality in xml.Descendants("Quality"))
    listFurniture.Add(quality.Value);

maintextbox.Text = listFurniture[0];

......这个例子是xml

<Furniture>
  <Table>
    <Quality>textbox1.Text + "and" + textbox2.Text + "but" + textbox3.Text</Quality>   
    ...
  </Table>  
</Furniture>

我的困境是,maintextbox正在生成实际的字符串“textbox1.Text”,而不是textbox1的值。

我希望将xml值读作:

maintextbox.Text = textbox1.Text + "and" + textbox2.Text + "but" + textbox3.Text;

不是:

maintextbox.Text = "textbox1.Text + "and" + textbox2.Text + "but" + textbox3.Text";

我尝试使用文本文件以及StreamReader,我得到了相同的结果。

以这种方式编写项目的原因是因为文本框的顺序发生了变化,“and”和“but”也发生了变化。当发生这种变化时,我不必重写代码并重新编译程序。我只想在xml中进行更改。

2 个答案:

答案 0 :(得分:2)

您的解决方案中的xml解析都可以。您需要的是处理Quality字符串。

string[] parts = quality.Split('+');
Regex regex = new Regex(@"^""(.*)""$");
var textBoxes = Controls.OfType<TextBox>().ToList();

for (int i = 0; i < parts.Length; i++)
{
    string part = parts[i].Trim();

    var match = regex.Match(part);
    if (match.Success)
    {
        parts[i] = match.Groups[1].Value;
        continue;
    }

    var textBox = textBoxes.FirstOrDefault(tb => tb.Name + ".Text" == part);
    if (textBox != null) // possibly its an error if textbox not found
        parts[i] = textBox.Text; 
}    

mainTextBox.Text = String.Join(" ", parts);

这里发生了什么:

  • 我们通过+字符拆分质量字符串以获取字符串部分数组
  • 使用正则表达式,我们验证部分是否与引号"something"中的内容相似。如果是,那么它将是orand或其他连接词
  • 最后,我们检查所有文本框中是否匹配质量字符串部分中文本框的名称。如果匹配,那么我们用textbox
  • 中的文本替换部分
  • 我们加入部分以获取结果字符串

BTW你可以在一行中解析Xml:

var listFurniture = xml.Descendants("Quality") 
                       .Select(q => (string)q)
                       .ToList();

答案 1 :(得分:1)


更新

因为我收到一条评论来解释一下代码;我会解释一下。

首先,XML作为一种语言是为结构而设计的。那种结构和轻松;提供灵活性和功能,可以无缝地快速解析语言或应用程序之间的数据。您的原始问题表明您的文本框正在生成代码textbox.text的字符串值。

需要构建XML;示例结构将是:

<Furniture>
     <Table>
         <Color> Red </Color>
         <Quality> 10 </Quality>
         <Material> Wood </Material>
      </Table>
</Furniture>

因此,如果您要阅读XML,则会找到root标记。所有其他组件都是nodes。这些节点需要索引或虹吸,以获得您希望在文本框中显示的正确关联。

这就是这段代码的作用;我会在每一步都将其分解。

// String you will format with the XML Structure.
StringBuilder output = new StringBuilder();

下一部分如下:

// Create an XML Reader, by wrapping it in the 'using' it will ensure once your done the object is disposed of.  Rather then leaving the connection to your document open.
using (XmlReader reader = XmlReader.Create(new StringReader(xmlString)))
{
       // We will read our document to the following; hold to that attribute.  The attribute is identifying the node and all of the child elements that reside within it: So in our case Table.
       reader.ReadToFollowing("Table");
       reader.MoveToFirstAttribute();
       string color = reader.Value;
       output.AppendLine("The color of the table " + color);

       // As you can see there isn't anything fancy here, it reads to our root node.  Then moves to the first child element.  Then it creates a string and appends it. Keep in mind we are using our StringBuilder so we are just appending to that structure.
       reader.ReadToFollowing("Material");
       output.AppendLine("The material: " + reader.ReadElementContentAsString());

       // Same result as we used earlier; just a different method to attain our value.
}

// Now we output our block.
OutputTextBlock.Text = output.ToString();

现在所有数据都被推送到字符串中,显然你可以使用上面的代码和文本框来检索这些值。

这就是您正确地将XML接收到应用程序中的方式;但你之前提到过两件事。所以听起来你试图使用文本框来物理地写入文档,这可以通过XmlWriter来完成。

但是,您还会继续接收文本框,因为就文本框而言textbox.text与值相关联。您的结构声明此字符串是值。

为了实现你的目标;你会有一个方法将值写入文档。然后另一个读它;这样就可以正确地将数据转入和转出文档并正确表示。

<Quality>Textbox1.Text</Quality>这不允许文本框值自动读入您的文档和文本框。您将字符串值分配给节点。在读取之前,您将需要在文档中写入值。

MSDN提供了如何正确解析数据的示例;希望我已经澄清了你遇到问题的一些原因。


更多代码;直接来自MSDN: 在MSDN上:

StringBuilder output = new StringBuilder();

String xmlString =
        @"<?xml version='1.0'?>
        <!-- This is a sample XML document -->
        <Items>
          <Item>test with a child element <more/> stuff</Item>
        </Items>";
// Create an XmlReader
using (XmlReader reader = XmlReader.Create(new StringReader(xmlString)))
{
    XmlWriterSettings ws = new XmlWriterSettings();
    ws.Indent = true;
    using (XmlWriter writer = XmlWriter.Create(output, ws))
    {

        // Parse the file and display each of the nodes.
        while (reader.Read())
        {
            switch (reader.NodeType)
            {
                case XmlNodeType.Element:
                    writer.WriteStartElement(reader.Name);
                    break;
                case XmlNodeType.Text:
                    writer.WriteString(reader.Value);
                    break;
                case XmlNodeType.XmlDeclaration:
                case XmlNodeType.ProcessingInstruction:
                    writer.WriteProcessingInstruction(reader.Name, reader.Value);
                    break;
                case XmlNodeType.Comment:
                    writer.WriteComment(reader.Value);
                    break;
                case XmlNodeType.EndElement:
                    writer.WriteFullEndElement();
                    break;
            }
        }

    }
}
OutputTextBlock.Text = output.ToString();

StringBuilder output = new StringBuilder();

String xmlString =
    @"<bookstore>
        <book genre='autobiography' publicationdate='1981-03-22' ISBN='1-861003-11-0'>
            <title>The Autobiography of Benjamin Franklin</title>
            <author>
                <first-name>Benjamin</first-name>
                <last-name>Franklin</last-name>
            </author>
            <price>8.99</price>
        </book>
    </bookstore>";

// Create an XmlReader
using (XmlReader reader = XmlReader.Create(new StringReader(xmlString)))
{
    reader.ReadToFollowing("book");
    reader.MoveToFirstAttribute();
    string genre = reader.Value;
    output.AppendLine("The genre value: " + genre);

    reader.ReadToFollowing("title");
    output.AppendLine("Content of the title element: " + reader.ReadElementContentAsString());
}

OutputTextBlock.Text = output.ToString();