我试图在.net环境中使用c#解析XML文件,它一直跳过元素
本文关键字:文件 XML 一直 元素 解析 net 环境 | 更新日期: 2023-09-27 18:16:28
这就是我试图解析的XML的一部分:
<azsa:Views>
<azsa:Spatial_Array>
<azsa:Spatial>
<azsa:ViewName>Spatial</azsa:ViewName>
<azsa:BBox>
<azsa:PointLo>
<azsa:x>0</azsa:x>
<azsa:y>0</azsa:y>
<azsa:z>0</azsa:z>
</azsa:PointLo>
<azsa:PointHi>
<azsa:x>2925</azsa:x>
<azsa:y>3375</azsa:y>
<azsa:z>2775</azsa:z>
</azsa:PointHi>
</azsa:BBox>
</azsa:Spatial>
</azsa:Spatial_Array>
</azsa:Views>
我必须读取PointHi和PointLo的x,y和z坐标
我使用XMLReader()类来执行任务。
XmlTextReader reader = new XmlTextReader(openFileDialog1.FileName);
while (reader.Read())
{
reader.ReadToFollowing("azsa:Views");
reader.ReadToFollowing("azsa:Spatial_Array");
reader.ReadToFollowing("azsa:Spatial");
reader.ReadToFollowing("azsa:ViewName");
reader.ReadToFollowing("azsa:BBox");
reader.ReadToFollowing("azsa:PointLo");
reader.ReadToFollowing("azsa:x");
low[0] = (int)(Double.Parse(reader.ReadElementString()));
reader.ReadToFollowing("azsa:y");
low[1] = (int)(Double.Parse(reader.ReadElementString()));
reader.ReadToFollowing("azsa:z");
low[2] = (int)(Double.Parse(reader.ReadElementString()));
reader.ReadToFollowing("azsa:PointHi");
reader.ReadToFollowing("azsa:x");
high[0] = (int)(Double.Parse(reader.ReadElementString()));
reader.ReadToFollowing("azsa:y");
high[1] = (int)(Double.Parse(reader.ReadElementString()));
reader.ReadToFollowing("azsa:z");
high[2] = (int)(Double.Parse(reader.ReadElementString()));
}
阅读器工作得很好,直到它到达PointLo中的第一个x,然后它直接跳到PointHi中的y。我试过使用后代,子树和readinnerxml,但它仍然做同样的事情。
注意:1。在while循环中有更多的代码用于读取XML的其余部分,但对于这个问题不是必需的,所以我没有将其包含在帖子中。2. 更改XML的组织方式是不可能的,因为这是我正在执行的任务所要求的存储方式。3.XMLReader是更可取的方法,因为我正在处理大量文档,并且没有使用此缓存内存的范围。
我有一个相当类似的问题,当读取子树。该场景中的解决方案是处理子树XmlReaders。当然,这里的情况略有不同,但是您是否可以考虑如下方法(注意,为了简化测试,我删除了元素前缀,并且读取XML字符串而不是文件)?
它确实看起来很丑,但这更多的是一个概念的证明,可以整理一下。它还缺少适当的错误检查,但这也是出于演示目的。它至少可以解析出不同的点值。
作为附注,我认为通过创建类来表示XML流中的不同组件(或对象),并使这些类负责解析出它们自己的属性,也许可以将许多丑陋的东西抽象掉。
这只是一种(我敢肯定)剥猫皮的方法…
private void ParseXml(string xml)
{
double[] low = null;
double[] hi = null;
using (StringReader stringReader = new StringReader(xml))
{
using (XmlReader xmlReader = XmlReader.Create(stringReader))
{
while (xmlReader.Read())
{
if (xmlReader.NodeType != XmlNodeType.Element) continue;
if (xmlReader.Name == "PointLo")
{
low = ParsePoint(xmlReader);
}
else if (xmlReader.Name == "PointHi")
{
hi = ParsePoint(xmlReader);
}
}
}
}
}
private double[] ParsePoint(XmlReader xmlReader)
{
double[] point = new double[3];
using (XmlReader pointReader = xmlReader.ReadSubtree())
{
while (pointReader.Read())
{
if (pointReader.NodeType != XmlNodeType.Element) continue;
if (pointReader.Name == "x")
{
point[0] = GetDimensionValue(pointReader);
}
else if (pointReader.Name == "y")
{
point[1] = GetDimensionValue(pointReader);
}
else if (pointReader.Name == "z")
{
point[2] = GetDimensionValue(pointReader);
}
}
}
return point;
}
private double GetDimensionValue(XmlReader reader)
{
using (XmlReader dimensionReader = reader.ReadSubtree())
{
dimensionReader.Read();
return reader.ReadElementContentAsDouble();
}
}
因此,正如我在对manderson的解决方案的评论中提到的那样,由于某种原因,它没有将y元素视为元素,而是将其视为文本元素,我对ParsePoint()
中的while循环进行了以下更改 while (pointReader.Read())
{
if (pointReader.NodeType == XmlNodeType.Element || pointReader.NodeType== XmlNodeType.Text)
{
if (pointReader.Name == "azsa:x")
{
point[0] = pointReader.ReadElementContentAsDouble();
}
else if (pointReader.Name == "")
{
point[1] = Double.Parse(pointReader.Value);
}
else if (pointReader.Name == "azsa:z")
{
point[2] = pointReader.ReadElementContentAsDouble();
}
}
}
虽然我不是说这是理想的方法,但它适用于我正在处理的XML文件。我还删除了GetDimensionValue方法,只读取该方法本身的值/元素内容。