value吞噬嵌入的XML

本文关键字:XML 吞噬 value | 更新日期: 2023-09-27 18:17:35

我的问题:我正在将一堆基于XML的日志(我几乎无法控制)解析为MySQL语句,以便从基于XML的数据库切换到MySQL。这一点把我难住了。

如果我查看包含感兴趣的字符串的IEnumerable<XElement>,我可以看到嵌入的XML语句。但是,如果取该字符串的值,XML语句就消失了。如:

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()

我得到同样的结果

程序:如果你把下面的c#语句粘贴到LinqPad中,你就会明白我的意思了。XML标记<PowerFail />消失。我注意到它也会在这里消失,除非我在它周围加上反勾。我包含了LinqPad标签,因为这就是我解析这些文件的方式(有成千上万的日志文件可以追溯到几年前),使用一系列的LinqPad脚本将日志处理到MySQL中,并插入它们以创建新的数据库。

我的问题:我意识到我可以用一些正则表达式或子字符串或其他东西来得到字符串,但似乎我应该能够得到整个字符串,标签&都来自IEnumerable,但是怎么做呢?另外,我很想知道为什么标签被吞下只是为了我的启发。

我有大约36个这些类型的日志异常的变体,影响了成千上万的日志(我昨天修复的最后一个应用于1500+日志)跨越七年左右的数据,所以我想找到一个(更)通用的解决方案,而不是XML标记特定的正则表达式,子字符串或任何东西。我不能更改日志,我不想在传输到新数据库时丢失数据。

直接查看问题:切,粘贴到LinqPAD作为c#语句(是否有一个在线的方法来做这个类似于JavaScript的JSFiddle)?我在底部添加了一个正则表达式解决方案,以防有人来寻找类似的东西,但我仍然对更好的方法感兴趣。

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);

value吞噬嵌入的XML

作为XElement的MSDN文档。值表示:

获取或设置此元素的连接文本内容。

因此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();

但正如链接问题所说:这些比使用阅读器慢得多。