C#: XmlTextWriter.WriteElementString在空字符串上失败?

9

我正在使用 XmlTextWriter 和它的 WriteElementString 方法,例如:

XmlTextWriter writer = new XmlTextWriter("filename.xml", null);

writer.WriteStartElement("User");
writer.WriteElementString("Username", inputUserName);
writer.WriteElementString("Email", inputEmail);
writer.WriteEndElement();

writer.Close();

预期的XML输出为:
<User>
    <Username>value</Username>
    <Email>value</Email>
</User>

然而,如果例如输入的电子邮件为空,则我得到的结果XML如下所示:
<User>
    <Username>value</Username>
    <Email/>
</User>

我原本期望的是:

<User>
    <Username>value</Username>
    <Email></Email>
</User>

我做错了什么?有没有一种简单的方法可以使用 XmlTextWriter 来实现我的预期结果?

5个回答

23

您的输出是正确的。没有内容的元素应该写成<tag/>

您可以通过调用WriteFullEndElement()来强制使用完整标签。

writer.WriteStartElement("Email");
writer.WriteString(inputEmail);
writer.WriteFullEndElement();

当inputEmail为空时,将输出<Email></Email>

如果您想要多次执行此操作,可以创建扩展方法:

public static void WriteFullElementString(this XmlTextWriter writer,
                                          string localName, 
                                          string value)
{
    writer.WriteStartElement(localName);
    writer.WriteString(value);
    writer.WriteFullEndElement();
}

那么您的代码将变成:

writer.WriteStartElement("User");
writer.WriteFullElementString("Username", inputUserName);
writer.WriteFullElementString("Email", inputEmail);
writer.WriteEndElement();

我使用了您提供的完全相同的解决方案,但 WriteFullEndElement() 方法似乎不起作用... 我认为这个方法有问题。 - Dave Thompson
我在C#中找到了一个解决方法。如果(string.Length == 0),则用换行转义字符"\n"替换空字符串。 - Dave Thompson

5

这并不是失败了,<Tag/>只是<Tag></Tag>的一种简写方式。


可以强制让它输出 <Tag></Tag> 吗? - Roee Adler
如果这是一个问题,你完全有权利对那些要求你完整书写标签的人大喊大叫;他们需要遵循基本的XML规范。 - Nyerguds

2

你的代码应该是:

using (XmlWriter writer = XmlWriter.Create("filename.xml"))
{
    writer.WriteStartElement("User");
    writer.WriteElementString("Username", inputUserName);
    writer.WriteElementString("Email", inputEmail);
    writer.WriteEndElement();
}

这样做可以避免异常导致的资源泄漏,并使用正确的方式创建XmlReader(自.NET 2.0起)。

0

尝试用另一种方法解决这个问题,可能需要优化。

public class SerializeConfig<T> where T : class
{
        public static string Serialize(T type)
        {
            var settings = new XmlWriterSettings
            {
                Encoding = Encoding.UTF8,
                Indent = true,
                OmitXmlDeclaration = true
            };
            var sb = new StringBuilder();
            var serializer = new XmlSerializer(type.GetType());
            using (var writer = XmlWriter.Create(sb, settings))
            {
                serializer.Serialize(writer, type);
            }

            return sb.ToString().FixXmlClosingTags();
        }
}
internal static class InsertStringExtention
{
    public static string FixXmlClosingTags(this string xmlString)
    {
        var sb = new StringBuilder();
        var xmlTags = xmlString.Split('\r');
        foreach (var tag in xmlTags)
        {
            if (tag.Contains("/>"))
            {
                var tagValue = tag.Replace("<", "").Replace("/>", "").Trim();
                var firstPart = tag.Substring(0, tag.IndexOf('<'));
                var newTag = $"{firstPart}<{tagValue}></{tagValue}>";
                sb.Append(newTag);
            }
            else
            {
                sb.Append(tag);
            }
            
        }
        return sb.ToString();
    }
}

0

我把这个留在这里,以防有人需要;因为上面的答案都没有解决我的问题,或者看起来过于复杂。

FileStream fs = new FileStream("file.xml", FileMode.Create);

XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;

XmlWriter w = XmlWriter.Create(fs, settings);
w.WriteStartDocument();
w.WriteStartElement("tag1");
w.WriteStartElement("tag2");
w.WriteAttributeString("attr1", "val1");
w.WriteAttributeString("attr2", "val2");
w.WriteFullEndElement();
w.WriteEndElement();
w.WriteEndDocument();

w.Flush();
fs.Close();

关键是要设置 XmlWriterSettings.Indent = true 并将其添加到 XmlWriter 中。

编辑:

或者您也可以使用

w.Formatting = Formatting.Indented;

不要添加XmlWriterSettings,而是使用以下方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接