我的问题: 我正在将一堆基于XML的日志(我几乎无法控制)解析为MySQL语句,以便从基于XML的数据库切换到MySQL。这一点让我难过。
如果我查看包含我感兴趣的字符串的IEnumerable<XElement>
,我可以看到嵌入式XML语句。但是,如果我获取该字符串的值,则XML语句将消失。 EG:
IEnumerable(<PowerFail />
可见):
<StepDetails>Set input voltage to 2.80V WDT should allow CPU power. CPU should detect PowerFail signal and output a<PowerFail /> tag to the serial line. WDT should reset every 1.6 seconds</StepDetails>
取值后,字符串中缺少<PowerFail />
标记:
Set input voltage to 2.80V WDT should allow CPU power. CPU should detect PowerFail signal and output a tag to the serial line. WDT should reset every 1.6 seconds
如果我做.ToString()
步骤:
如果您将以下内容粘贴到LinqPad作为C#语句,您可以看到我的意思。 XML标记<PowerFail />
消失了。 我注意到它也会在这里消失,除非我在它周围留下滴答声。我已经包含了LinqPad标签,因为我正在解析这些文件(有数万个日志文件可以追溯到几年前)使用一系列LinqPad脚本将日志处理成MySQL并插入它们以创建新数据库。
我的问题: 我意识到我可以用一些正则表达式或子串或其他东西来获取字符串,但似乎我应该能够得到整个字符串,标签和&amp;全部来自IEnumerable,但怎么办呢?此外,我很想知道为什么标签被吞下来只是为了我的启发。
我有大约三十种这类日志异常的变种影响了成千上万的日志(我昨天修复的最后一个日志仅应用于1500多个日志),大约七年左右的数据,所以我想找到一个(更多)通用解决方案,而不是XML标签特定的正则表达式,子字符串或其他每个。我无法更改日志,我不想在传输到新数据库时丢失数据。
第一手查看问题: 剪切&amp;粘贴到LinqPAD作为C#语句(是否有类似JSFiddle for JavaScript的在线方式)?我已经在底部添加了一个正则表达式解决方案,以防有人来寻找类似的东西,但我仍然对更好的方法感兴趣。
string xml = @"<StepResults>
<TestStep Name='2.8V OPERATION' Result='Pass'>
<OperatorComment/>
<StepDetails>Set input voltage to 2.80V WDT should allow CPU power. CPU should detect PowerFail signal and output a<PowerFail/> tag to the serial line. WDT should reset every 1.6 seconds</StepDetails>
<Measurements NumberOfMeasurements='1'>
<Measurement Name='BATTERY VOLTAGE: VOLTS'>
<MeasuredValue>2.794608</MeasuredValue>
<Min>2.785000</Min>
<Max>2.800000</Max>
</Measurement>
</Measurements>
</TestStep>
</StepResults>";
var xd = XDocument.Parse(xml);
Console.WriteLine(xd);
var xe =
from e in xd.Descendants("StepDetails")
select e;
Console.WriteLine(xe);
Console.WriteLine(xe.First().Value);
//new code below to show a working regex solution:
string stepDetail = xe.First().ToString();
Regex matchFrontTag = new Regex("^<[^>]*>");
Regex matchRearTag = new Regex("<[^>]*>$");
stepDetail = matchFrontTag.Replace(stepDetail,string.Empty);
stepDetail = matchRearTag.Replace(stepDetail,string.Empty);
Console.WriteLine(stepDetail);
答案 0 :(得分:1)
正如MSDN documentation for XElement.Value所说:
获取或设置此元素的连接文本内容。
所以XElement.Value
确实只会返回文本节点,并且(在混合内容的情况下)会忽略非文本节点(但不包含其中包含的文本节点)。
您正在寻找XElement的内部XML,您可以使用XmlReader获取它。
// this writes only the (concatenated) text nodes
Console.WriteLine(xe.First().Value);
// this writes the inner XML, including elements
var reader = xe.First().CreateReader();
reader.MoveToContent();
Console.WriteLine(reader.ReadInnerXml());
如果你更喜欢留在LINQ中,你可以简单地加入所有子节点的字符串表示:
Console.WriteLine(
xe.First().Nodes().Aggregate("", (result, node) => result += node.ToString())
);
或者
string.Join("", xe.First().Nodes().Select(n => n.ToString())).Dump();
但正如相关问题所说:这些比使用阅读器慢得多。