c# - 我在将数据从 XML 文件移动到具有 CDATA 节点类型的 ARRAY 时遇到问题
问题描述
根据标题,从带有CDATA
元素的 XML 文件获取数据到数组中时遇到问题。基于我目前对如何做的有限理解,我想出了这个基本的工作方法
CDATA
很奇怪,所以我的正常方法不起作用。我找到节点的正常路线并没有停在它们上面,然后就是整个CDATA
问题。
XmlTextReader xmlReader = new XmlTextReader(FilePath);
while (xmlReader.Read())
{
// Position the reader on the OrderNumber node
xmlReader.ReadToFollowing("quoteNumber");
XmlReader inner = xmlReader.ReadSubtree();
while (inner.Read())
{
switch (xmlReader.NodeType)
{
case XmlNodeType.CDATA:
Globals.COData[0] = inner.Value;
break;
}
}
xmlReader.ReadToFollowing("orderNumber");
inner = xmlReader.ReadSubtree();
while (inner.Read())
{
switch (xmlReader.NodeType)
{
case XmlNodeType.CDATA:
Globals.COData[1] = inner.Value;
break;
}
}
但是我有很多数据元素要获取并假设有更好的方法。文件看起来像:
以及相关部分:
<quoteNumber>
<![CDATA[ John Test 123]]>
</quoteNumber>
<orderNumber>
<![CDATA[ 1352738]]>
</orderNumber>
包含的项目在文件末尾确实有一个结束元素。整个 XML 太大而无法发布。
XML 格式不在我的控制范围内。
我的最终目标是将OrderNumber
其及其值放入一个数组中。及其Quote number
价值。我习惯于看到<OrderNumber>123</OrderNumber>
这样CDATA
的节点对我来说是新的。
解决方案
由于您没有共享完整的 XML,因此并不完全清楚您哪里出错了,但是您没有从循环XmlReader.ReadToFollowing(string)
内部检查返回值。Read()
因此,一旦你读过最后一个,当没有找到<orderNumber>
另一个时你会得到一个异常。<quoteNumber>
我建议重组你的代码如下:
var ns = ""; // Replace with @"http://intelliquip.com/integrationS..." can't see the full namespace from the XML image.
var list = new List<Tuple<string, string>>(); // List of (quoteNumber, orderNumber) values.
var xmlReader = XmlReader.Create(FilePath);
while (xmlReader.ReadToFollowing("quoteNumber", ns))
{
string quoteNumber = null;
string orderNumber = null;
using (var inner = xmlReader.ReadSubtree())
{
// We need to skip the insignificant whitespace around the CDATA nodes which ReadElementContentAsString() will not do.
while (inner.Read())
{
switch (xmlReader.NodeType)
{
case XmlNodeType.Text:
case XmlNodeType.CDATA:
quoteNumber += inner.Value;
break;
}
}
// After ReadSubtree() the reader is positioned on the </quoteNumber> element end.
}
// If the next orderNumber node is nmissing, ReadToFollowing() will read all the way past the next quoteNumber node.
// Use ReadToNextSibling() instead.
if (xmlReader.ReadToNextSibling("orderNumber", ns))
{
using (var inner = xmlReader.ReadSubtree())
{
while (inner.Read())
{
switch (xmlReader.NodeType)
{
case XmlNodeType.Text:
case XmlNodeType.CDATA:
orderNumber += inner.Value;
break;
}
}
}
}
if (quoteNumber != null && orderNumber != null)
list.Add(Tuple.Create(quoteNumber, orderNumber));
else
{
// Add error handling here
}
}
笔记:
CDATA
只是编码 XML 字符数据节点的另一种方法,请参阅 XML中的<![CDATA[]]> 是什么意思?详情。XmlReader.Value
将包含 XML 字符数据节点的未转义值,无论它是编码为常规文本节点还是CDATA
节点。从您的问题中不清楚 XML 文件中是否必须只有一个
<quoteNumber>
节点。因此,我将报价和订单号对读入List<Tuple<string, string>>
. 阅读完成后,您可以检查已阅读的数量,然后Globals.COData
酌情添加。-
true
如果找到匹配元素;否则false
处于XmlReader
文件结束状态。因此,需要检查它的返回值,以确保您不会尝试读取文件末尾。
您的代码不会尝试处理
<orderNumber>
缺少 an 的情况。如果是,则代码可能会一直跳过下一个<quoteNumber>
以读取其订单号。为了避免这种可能性,我使用XmlReader.ReadToNextSibling()
将搜索范围限制为<orderNumber>
属于同一父节点的节点。通过使用
XmlReader.ReadToFollowing("orderNumber")
硬编码代码来假设orderNumber
节点没有命名空间前缀。与其这样做,不如明确指出它们所在的名称空间,这似乎类似于未显示http://intelliquip.com/integrationS...
该部分的位置。...
我建议使用
XmlReader.ReadToFollowing("orderNumber", ns)
wherens
是 order 和 quote 节点实际所在的命名空间。XmlTextReader
自 .Net 2.0 以来已被弃用。改为使用XmlReader.Create()
。API使用
XmlReader
起来相当繁琐。如果您的 XML 文件不大,您可以考虑将它们加载到LINQ to XML 中XDocument
并使用LINQ to XML来查询它。例如,您的
XmlReader
代码可以重写如下:var doc = XDocument.Load(FilePath); XNamespace ns = ""; // Replace with @"http://intelliquip.com/integrationS..." can't see the full namespace from the XML image. var query = from quote in doc.Descendants(ns + "quoteNumber") let order = quote.ElementsAfterSelf(ns + "orderNumber").FirstOrDefault() where order != null select Tuple.Create(quote.Value, order.Value); var list = query.ToList();
这看起来要简单得多。
您也可以考虑将 替换
Tuple<string, string>
为适当的数据模型,例如public class Order { public string QuoteNumber { get; set; } public string OrderNumber { get; set; } }
Demo fiddle #1 here for XmlReader
and #2 here for LINQ to XML。
推荐阅读
- c++ - 检查是否至少有一个 Wayland 会话正在运行
- android - 在视图/活动/片段可见后,每 5 分钟显示一个警报对话框的最佳方法是什么?
- console - Vala 如何输出没有循环的数组?
- r - 仅合并 r 中的不同行
- c++ - 重载 operator+ 后程序崩溃
- rest - 如何通过 REST API 设置 IBM MQ 消息的优先级?
- python - 两个数据框之间的差异并删除两者中都不存在的数据框
- android - 当应用程序处于终止状态时数据离线同步
- excel - 检查 Wistia 的有效 URL
- reactjs - TypeError:无法读取未定义的属性“绑定” - ReactJS - 测试库