省略XML声明?

时间:2014-02-17 19:42:34

标签: c# xelement

我有一个XElement,我必须解析它以删除结束标记中的空白区域。我的代码如下所示:

var stringBuilder = new StringBuilder();
using (var stringWriter = new StringWriter(stringBuilder))
{
    xelement.Save(stringWriter);
}
stringBuilder.Replace(" />", "/>");
var xml = stringBuilder.ToString();

基本上,我正在制作一个stringbuilder并替换不需要的空格。结果字符串看起来很好,除了它有XML声明。我知道在XmlWriter上,我可以省略OmitXmlDeclaration的声明,但StringWriter没有这个。

有没有办法做到这一点,还是我需要从结果字符串中手动解析声明?

为清楚起见,这里是XML之前和之后:

// Before
<actionitem actiontaken="none" target="0" targetvariable="0">
  <windowname>Popup Window</windowname>
  <windowposx>-1</windowposx>
  <windowposy>-1</windowposy>
  <windowwidth>-1</windowwidth>
  <windowheight>-1</windowheight>
  <noscrollbars>false</noscrollbars>
  <nomenubar />
  <notoolbar />
  <noresize />
  <nostatus />
  <nolocation />
  <browserWnd />
</actionitem>

// After
<?xml version="1.0" encoding="utf-16"?>
<actionitem actiontaken="none" target="0" targetvariable="0">
  <windowname>Popup Window</windowname>
  <windowposx>-1</windowposx>
  <windowposy>-1</windowposy>
  <windowwidth>-1</windowwidth>
  <windowheight>-1</windowheight>
  <noscrollbars>false</noscrollbars>
  <nomenubar/>
  <notoolbar/>
  <noresize/>
  <nostatus/>
  <nolocation/>
  <browserWnd/>
</actionitem>
编辑:对于那些提出的问题,这是针对国防部的一个项目。它们的规格被锁定。这意味着,无论我多么抗议,关闭标签中都没有空白区域。无论是否正确是什么,他们都不想要它,而且他们正在签署薪水。我只是试着容纳他们。

2 个答案:

答案 0 :(得分:3)

使用ToString()代替Save()。这也消除了对StringBuilder的需求。

 string xml = xelement.ToString(); // no declaration element added
 xml = xml.Replace(" />", "/>");   // if you really think you must

答案 1 :(得分:2)

免责声明:此答案仅适用于Kevin J和Kevin J.不要对XML执行字符串操作。

如果你仍然想使用StringBuilder / StringWriter,你可以通过StringWriter TextWriterXmlWriter}连接{<1}}:

var xe = new XElement("test",
    new XElement("child1"),
    new XElement("child2"));

var sb = new StringBuilder();
using (var writer = new StringWriter(sb))
using (var xr = XmlWriter.Create(writer, new XmlWriterSettings()
{
    OmitXmlDeclaration = true
}))
{
    xe.Save(xr);
}

sb.Replace(" />", "/>");

至于Replace我写了一个函数,应该对角落案例(评论,CData)更具弹性。 也应该使用更少的周期并消耗更少的内存。

static void StripClosingWhitespace(StringBuilder sb)
{
    var inComment = false;
    var inCData = false;

    for (var i = 0; i < sb.Length; i++)
    {
        var c = sb[i];
        if (inComment)
        {
            if (c == '>' && sb[i - 1] == '-' && sb[i - 2] == '-')
                inComment = false;
        }
        else if (inCData)
        {
            if (c == '>' && sb[i - 1] == ']' && sb[i - 2] == ']')
                inCData = false;
        }
        else if (i > 2 && c == '-' && sb[i - 1] == '-' && sb[i - 2] == '!' && sb[i - 3] == '<')
        {
            inComment = true;
        }
        else if (i > 7 && 
            c == '[' && 
            sb[i - 1] == 'A' && sb[i - 2] == 'T' && sb[i - 3] == 'A' && sb[i - 4] == 'D' && sb[i - 5] == 'C' &&
            sb[i - 6] == '[' && sb[i - 7] == '!' && sb[i - 8] == '<')
        {
            inCData = true;
        }
        else if (i > 2 && c == '>' && sb[i - 1] == '/' && char.IsWhiteSpace(sb[i - 2]))
        {
            sb.Remove(i - 2, 1);
            i--;
        }
        else
        {
            // Do nothing
        }
    }
}