[英]Best way to parse XML Attributes
我有以下XML文檔需要解析:
...
<tx size_total="143">
<type size="1" start_key="02">STX</type>
<type size="3">Type</type>
<type size="3" decimal="true">Serial</type>
<type size="3" key="23 64 31">Function_Code</type>
<type size="2" decimal="true">LIU</type>
<type size="1">Status</type>
<type size="2" repeat="64" binary ="true" binary_discard="2">Value</type>
<type size="1">ETX</type>
<type size="1">LRC</type>
...
我編寫了以下代碼進行解析:
XmlNodeList typeNodeList = txNode.SelectNodes(TYPE_NODE);
CommRuleContainer rc = new CommRuleContainer(funcNode.Attributes.GetNamedItem("name").Value,
txNode.Attributes.GetNamedItem("size_total").Value, funcNode.Attributes.GetNamedItem("id").Value);
foreach (XmlNode tNode in typeNodeList)
{
int size = Convert.ToInt32(tNode.Attributes.GetNamedItem("size").Value);
int repeat = Convert.ToInt32(tNode.Attributes.GetNamedItem("repeat").Value);
int binary_discard = Convert.ToInt32(tNode.Attributes.GetNamedItem("binary_discard").Value);
string start_key = tNode.Attributes.GetNamedItem("start_key").Value;
string key = tNode.Attributes.GetNamedItem("key").Value;
bool convert_decimal = false, convert_binary = false;
if (tNode.Attributes.GetNamedItem("decimal").Value == "true")
convert_decimal = true;
if (tNode.Attributes.GetNamedItem("binary").Value == "true")
convert_binary = true;
rc.AddTypeDefinition(tNode.Value, size, repeat, binary_discard, convert_decimal, convert_binary);
}
如果我嘗試獲取不存在的certian屬性的值,則代碼將引發nullreferenceexception(IE:tNode.Attribute.GetNamedItem(“ repeat”)。value在所有沒有重復屬性的節點上都失敗)。 我可以通過什么方法來驗證某個屬性是否存在?
上面的代碼也不是干凈的。 整理以上代碼的最佳方法是什么?
編輯:我知道一種方法,您可以在獲取值之前分別檢查屬性是否為null,但這會使代碼看起來很臟,因為我需要編寫大量的if(或嵌套的if)
if (tNode.Attributes.GetNamedItem("decimal") != null)
if (tNode.Attributes.GetNamedItem("decimal").Value == "true")
convert_decimal = true;
從長遠來看,如果我不得不編寫更多的屬性,這將成為問題。 我想更多地了解一種有組織的方法(也許可以枚舉XML屬性?我不知道。)
if(null != tNode.Attributes.GetNamedItem("repeat"))
repeat = Convert.ToInt32(tNode.Attributes.GetNamedItem("repeat").Value);
更新
現在您知道不會獲得空引用,
最好的解決方案是編寫一個類,使用XmlSerializer
將xml反序列化到該類中。
有關自定義序列化的本文將幫助您入門。
要使用XML序列化,您必須首先使用指示所需XML映射的屬性標記數據對象。 這些屬性在System.Xml.Serialization命名空間中找到,包括以下內容:
XmlRoot指定XML文件的根元素的名稱。 默認情況下,XmlSerializer將使用該類的名稱。 該屬性可以應用於類聲明。
同意@nunespascal,這是我已經為您准備的代碼..他的回答比我更快..大聲笑:
static void Main(string[] args)
{
var serialized = @"
<tx size_total=""143"">
<type size=""1"" start_key=""02"">STX</type>
<type size=""3"">Type</type>
<type size=""3"" decimal=""true"">Serial</type>
<type size=""3"" key=""23 64 31"">Function_Code</type>
<type size=""2"" decimal=""true"">LIU</type>
<type size=""1"">Status</type>
<type size=""2"" repeat=""64"" binary =""true"" binary_discard=""2"">Value</type>
<type size=""1"">ETX</type>
<type size=""1"">LRC</type></tx>";
var deserialized = serialized.XmlDeserialize<Tx>();
}
}
[XmlRoot("tx")]
public class Tx
{
[XmlAttribute("size_total")]
public int TotalSize { get; set; }
[XmlElement("type")]
public List<TxType> Types { get; set; }
public Tx()
{
Types = new List<TxType>();
}
}
public class TxType
{
[XmlAttribute("size")]
public string Size { get; set; }
[XmlAttribute("decimal")]
public bool IsDecimal { get; set; }
[XmlAttribute("binary")]
public bool IsBinary { get; set; }
[XmlAttribute("start_key")]
public string StartKey { get; set; }
[XmlAttribute("key")]
public string Key { get; set; }
[XmlAttribute("repeat")]
public int Repeat { get; set; }
[XmlAttribute("binary_discard")]
public int BinaryDiscard { get; set; }
[XmlText]
public string Value { get; set; }
}
這是我的反序列化的幫助器類:
public static class StringExtensions
{
/// <summary>
/// Deserializes the XML data contained by the specified System.String
/// </summary>
/// <typeparam name="T">The type of System.Object to be deserialized</typeparam>
/// <param name="s">The System.String containing XML data</param>
/// <returns>The System.Object being deserialized.</returns>
public static T XmlDeserialize<T>(this string s)
{
var locker = new object();
var stringReader = new StringReader(s);
var reader = new XmlTextReader(stringReader);
try
{
var xmlSerializer = new XmlSerializer(typeof(T));
lock (locker)
{
var item = (T)xmlSerializer.Deserialize(reader);
reader.Close();
return item;
}
}
catch
{
return default(T);
}
finally
{
reader.Close();
}
}
}
那應該使您有個良好的開端。 祝好運。
好吧,這是一個完全未經測試的混搭功能,YMMV。
static class XmlNodeExtensions {
public static T GetAttrValue(this XmlNode node, string attrName) {
return GetAttrValue(node, attrName, default(T));
}
public static T GetAttrValue(this XmlNode node, string attrName, T defaultValue) {
var attr = node.Attributes.GetNamedItem(attrName);
if (attr != null) {
var value = attr.Value;
var tT = typeof(T); // target Type
if (tT.IsAssignableFrom(typeof(string)))
{
return (T)value;
} else
{
var converter = TypeDescriptor.GetConverter(tT);
if (converter.CanConvertFrom(typeof(string)))
{
return (T)converter.ConvertFrom(value);
} else
{
throw new InvalidOperationException("No conversion possible");
}
}
} else {
return defaultValue;
}
}
}
.. 然后 ..
var id = node.GetAttrValue<int>("size");
var name = node.GetAttrValue("name", "no name!");
var titleOrNull = node.GetAttrValue<string>("title");
.. 或者其他的東西。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.