透视并用单个字符串替换 XDocument 的嵌套元素数组
Pivot and replace XDocument's nested element array of chars with a single string
有XML这样的:
<ReplyMessage>
<tran>
<ser_num>305</ser_num>
<time>1490987995</time>
<source_type>0</source_type>
<source_number>0</source_number>
<tran_type>126</tran_type>
<tran_code>50</tran_code>
<t_diag>
<bfr>S</bfr>
<bfr>o</bfr>
<bfr>c</bfr>
<bfr>k</bfr>
<bfr>e</bfr>
<bfr>t</bfr>
<bfr></bfr>
<bfr>r</bfr>
<bfr>e</bfr>
<bfr>c</bfr>
<bfr>v</bfr>
<bfr></bfr>
<bfr>o</bfr>
<bfr>n</bfr>
<bfr></bfr>
<bfr>s</bfr>
<bfr>o</bfr>
<bfr>c</bfr>
<bfr>k</bfr>
<bfr>e</bfr>
<bfr>t</bfr>
<bfr>-</bfr>
<bfr>7</bfr>
<bfr>4</bfr>
<bfr>:</bfr>
<bfr></bfr>
<bfr>f</bfr>
<bfr>a</bfr>
<bfr>i</bfr>
<bfr>l</bfr>
<bfr>e</bfr>
<bfr>d</bfr>
<bfr></bfr>
<bfr>-</bfr>
<bfr></bfr>
<bfr>3</bfr>
<bfr>0</bfr>
<bfr>7</bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
</t_diag>
</tran>
</ReplyMessage>
我想用一个简单的字符串元素替换 <t_diag>
下的嵌套 <bfr>
元素数组:
<ReplyMessage>
<tran>
<ser_num>305</ser_num>
<time>1490987995</time>
<source_type>0</source_type>
<source_number>0</source_number>
<tran_type>126</tran_type>
<tran_code>50</tran_code>
<t_diag>
<bfr>Socket recv on socket-74: failed - 307</bfr>
</t_diag>
</tran>
</ReplyMessage>
因此,将来自 Whosebug 和 MSDN 的几篇文章拼凑在一起,我得出了这个方法,它完成了工作:
private XElement XmlPivotCharArrayToStr(XDocument xmlDoc, string parentName, string arrayName)
{
XElement parent = xmlDoc.Descendants().Where(n => n.Name == parentName).FirstOrDefault();
string st = string.Join("", parent.Elements(arrayName).Select(x => string.IsNullOrEmpty(x.Value) ? " " : x.Value)).TrimEnd();
parent.RemoveAll();
XElement newElement = new XElement(arrayName, st);
parent.Add(newElement);
return newElement;
}
这样调用:
//// Some initial cleanup to convert character array into string
XmlPivotCharArrayToStr(xmlDoc, parentName: "t_diag", arrayName: "bfr");
现在,这在我的特定上下文中有效,但我觉得可以进行一些改进:
- 有没有一种方法可以指定 parentName 的显式路径而不是使用 .Descendants() 方法?
- 有没有更好的方法来换出数组并用字符串替换它? - parent.RemoveAll() 可能有点矫枉过正。
- 有没有办法检测数组的结尾以避免使用 TrimEnd()
在此先感谢您提供任何提示 - 我希望其他人发现(改进版)这很有用。
您可以 select 使用 xpath 定位节点。为此,请使用扩展方法(添加 using System.Xml.XPath
)。那么就:
XElement parent = xmlDoc.XPathSelectElement(path);
你的 path
是 "/ReplyMessage/tran/t_diag"
。
我认为 RemoveAll
很好,但如果您有疑问 - 您可以删除 t_diag
本身,如下所示:
XElement newElement = new XElement(arrayName, st);
var grandParent = parent.Parent;
parent.Remove();
grandParent.Add(new XElement(parent.Name, newElement));
TrimEnd
没问题。要检测末尾的所有元素是否为空,您无论如何都需要观察所有元素 - 所以您不能做得更好。
有XML这样的:
<ReplyMessage>
<tran>
<ser_num>305</ser_num>
<time>1490987995</time>
<source_type>0</source_type>
<source_number>0</source_number>
<tran_type>126</tran_type>
<tran_code>50</tran_code>
<t_diag>
<bfr>S</bfr>
<bfr>o</bfr>
<bfr>c</bfr>
<bfr>k</bfr>
<bfr>e</bfr>
<bfr>t</bfr>
<bfr></bfr>
<bfr>r</bfr>
<bfr>e</bfr>
<bfr>c</bfr>
<bfr>v</bfr>
<bfr></bfr>
<bfr>o</bfr>
<bfr>n</bfr>
<bfr></bfr>
<bfr>s</bfr>
<bfr>o</bfr>
<bfr>c</bfr>
<bfr>k</bfr>
<bfr>e</bfr>
<bfr>t</bfr>
<bfr>-</bfr>
<bfr>7</bfr>
<bfr>4</bfr>
<bfr>:</bfr>
<bfr></bfr>
<bfr>f</bfr>
<bfr>a</bfr>
<bfr>i</bfr>
<bfr>l</bfr>
<bfr>e</bfr>
<bfr>d</bfr>
<bfr></bfr>
<bfr>-</bfr>
<bfr></bfr>
<bfr>3</bfr>
<bfr>0</bfr>
<bfr>7</bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
<bfr></bfr>
</t_diag>
</tran>
</ReplyMessage>
我想用一个简单的字符串元素替换 <t_diag>
下的嵌套 <bfr>
元素数组:
<ReplyMessage>
<tran>
<ser_num>305</ser_num>
<time>1490987995</time>
<source_type>0</source_type>
<source_number>0</source_number>
<tran_type>126</tran_type>
<tran_code>50</tran_code>
<t_diag>
<bfr>Socket recv on socket-74: failed - 307</bfr>
</t_diag>
</tran>
</ReplyMessage>
因此,将来自 Whosebug 和 MSDN 的几篇文章拼凑在一起,我得出了这个方法,它完成了工作:
private XElement XmlPivotCharArrayToStr(XDocument xmlDoc, string parentName, string arrayName)
{
XElement parent = xmlDoc.Descendants().Where(n => n.Name == parentName).FirstOrDefault();
string st = string.Join("", parent.Elements(arrayName).Select(x => string.IsNullOrEmpty(x.Value) ? " " : x.Value)).TrimEnd();
parent.RemoveAll();
XElement newElement = new XElement(arrayName, st);
parent.Add(newElement);
return newElement;
}
这样调用:
//// Some initial cleanup to convert character array into string
XmlPivotCharArrayToStr(xmlDoc, parentName: "t_diag", arrayName: "bfr");
现在,这在我的特定上下文中有效,但我觉得可以进行一些改进:
- 有没有一种方法可以指定 parentName 的显式路径而不是使用 .Descendants() 方法?
- 有没有更好的方法来换出数组并用字符串替换它? - parent.RemoveAll() 可能有点矫枉过正。
- 有没有办法检测数组的结尾以避免使用 TrimEnd()
在此先感谢您提供任何提示 - 我希望其他人发现(改进版)这很有用。
您可以 select 使用 xpath 定位节点。为此,请使用扩展方法(添加
using System.Xml.XPath
)。那么就:XElement parent = xmlDoc.XPathSelectElement(path);
你的 path
是 "/ReplyMessage/tran/t_diag"
。
我认为
RemoveAll
很好,但如果您有疑问 - 您可以删除t_diag
本身,如下所示:XElement newElement = new XElement(arrayName, st); var grandParent = parent.Parent; parent.Remove(); grandParent.Add(new XElement(parent.Name, newElement));
TrimEnd
没问题。要检测末尾的所有元素是否为空,您无论如何都需要观察所有元素 - 所以您不能做得更好。