我正在尝试解析从流中读入的xml文档,查找元素并将它们作为XElements返回。我希望能够创建一个更通用的读者来获取文档中的每个元素,以便我可以在调用函数中使用linq查询来过滤我想要的内容。因此,假设我想获得"标题"," book"和" bookdata"来自以下xml的元素:
<parent>
<header>
<data>text</data>
</header>
<books>
<book>
<bookdata>
<title>book 1 title</title>
<author>author 1</author>
</bookdata>
<otherinfo>info1</otherinfo>
</book>
<book>
<bookdata>
<title>book 2 title</title>
<author>author 2</author>
</bookdata>
<otherinfo>info2</otherinfo>
</book>
</books>
</parent>
我已根据Leonard Lobel
中的代码实现了以下内容private static IEnumerable<XElement> GetElements(Stream data)
{
using (XmlReader reader = CreateSecureXmlReader(data))
{
reader.MoveToContent();
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element)
{
var e = XElement.ReadFrom(reader) as XElement;
yield return e;
}
}
}
}
它被称为如下:
var elements = from el in GetElements(stream)
where el.Name == "header" ||
el.Name == "book" ||
el.Name == "bookdata"
select el;
foreach (var xElement in elements)
{
Console.WriteLine(xElement.Name);
}
问题在于,一旦它将元素作为XElement读取,它就会向前跳过并且无法在此元素中查找匹配项。即我得到输出:
header
因为读取并返回了标头(由于某种原因跳过了父级)。但随后它会读取&#34; books&#34;,将其作为XElement返回,此时我假设XmlReader接下来会查看&#34; books&#34;这只是一些结束元素和文档的结尾。它没有机会向内心寻找&#34; book&#34;和#34; bookdata&#34;。
在伦纳德·洛贝尔的例子中,他传递了他正在寻找的元素名称,但即使我传递了我想要的元素的名称,我仍然遇到了问题,其中&#34;预订&# 34;消费了它并没有在里面看到#book; bookdata&#34;。
如果有人知道如何查看所有元素并将它们作为XElements返回,或者有更好的解决方案来查找和返回元素及其子元素,那么我们将非常感激。
答案 0 :(得分:0)
实施leonard lobels方法(注意参数):
private static IEnumerable<XElement> StreamElements(string fileName, params string[] elementsName)
{
using (var rdr = XmlReader.Create(fileName))
{
rdr.MoveToContent();
while (rdr.Read())
{
if ((rdr.NodeType == XmlNodeType.Element) && (elementsName.Contains(rdr.Name)))
{
var e = XElement.ReadFrom(rdr) as XElement;
yield return e;
}
}
rdr.Close();
}
}
在您的代码中(这是一个示例,您可以按照自己的方式实现):
List<XElement> myElements = new List<XElement>();
foreach (var item in StreamElements("YourXMLfile.xml", "book", "bookdata", "header"))
{
myElements.Add(item);
}