[.NET]XML reader針對空節點的處理方式
在論談上有看到在問「XML reader "/>" 處理」,他使用以下的XML內容(有包含空節點,如Font & Line),如下,
<Font Family="Verdana" Size="7" Color="DarkRed" />
<Line Color="Red" />
</Root>
而程式是使用類似下面的程式(請先加入 using System.Xml, 及using System.IO Namespace),
@"<Root>
<Font Family=""Verdana"" Size=""7"" Color=""DarkRed"" />
<Line Color=""Red"" />
</Root>";
StringBuilder output = new StringBuilder();
using (XmlReader reader = XmlReader.Create(new StringReader(xmlString)))
{
XmlWriterSettings ws = new XmlWriterSettings();
ws.Indent = true;
using (XmlWriter writer = XmlWriter.Create(output, ws))
{
while (reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.Element: // The node is an element.
writer.WriteStartElement(reader.Name);
while (reader.MoveToNextAttribute()) // Read the attributes.
{
writer.WriteStartAttribute(reader.Name);
writer.WriteValue(reader.Value);
writer.WriteEndAttribute();
}
break;
case XmlNodeType.Text: //Display the text in each element.
writer.WriteString(reader.Value);
break;
case XmlNodeType.EndElement: //Display the end of the element.
writer.WriteEndElement();
break;
}
}
}
}
Console.Write(output.ToString());
但是輸出的結果,Font居然包含Line這個節點,如下,
<Font Family="Verdana" Size="7" Color="DarkRed">
<Line Color="Red" />
</Font>
</Root>
看程式,一個開始,一個結束很正常呀~
但是如果一步一步Trace後發現,如果是空的節點,跟本不會跑到case XmlNodeType.EndElement裡面去。
如果是上面的XML內容,會跑進case XmlNodeType.EndElement裡的只會有Root節點而已。所以就會產生錯誤的XML內容出來。
再看一下XmlTextReader的屬性列表中,筆者發現一個IsEmptyElement的屬性(取得值,指出目前節點是否為空項目 (例如, <MyElement/>))。
所以,應該要在case XmlNodeType.Element的處理中加入判斷是否為空節點(bool isEmptyElem = reader.IsEmptyElement;),如果是的話,就要在最後加入writer.WriteEndElement。
最後修改後的程式如下,
@"<Root>
<Font Family=""Verdana"" Size=""7"" Color=""DarkRed"" />
<Line Color=""Red"" />
</Root>";
StringBuilder output = new StringBuilder();
using (XmlReader reader = XmlReader.Create(new StringReader(xmlString)))
{
XmlWriterSettings ws = new XmlWriterSettings();
ws.Indent = true;
using (XmlWriter writer = XmlWriter.Create(output, ws))
{
while (reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.Element: // The node is an element.
bool isEmptyElem = reader.IsEmptyElement;
writer.WriteStartElement(reader.Name);
while (reader.MoveToNextAttribute()) // Read the attributes.
{
writer.WriteStartAttribute(reader.Name);
writer.WriteValue(reader.Value);
writer.WriteEndAttribute();
}
//因為是empty,結束時,要加上EndElement
if (isEmptyElem)
writer.WriteEndElement();
break;
case XmlNodeType.Text: //Display the text in each element.
writer.WriteString(reader.Value);
break;
case XmlNodeType.EndElement: //Display the end of the element.
writer.WriteEndElement();
break;
}
}
}
}
Console.Write(output.ToString());
這樣輸出就正常了,如下,
<Font Family="Verdana" Size="7" Color="DarkRed" />
<Line Color="Red" />
</Root>
所以使用XmlReader時,別忘了要考慮空節點哦!
參考資料
How to: Parse XML with XmlReader
Hi,
亂馬客Blog已移到了 「亂馬客 : Re:從零開始的軟體開發生活」
請大家繼續支持 ^_^