XML:
<root>
<item>
<href>http://myurl</href>
</item>
<item>
<href>http://myurl2</href>
</item>
</root>
XML数据存储在数据库表中。
我可以构建一个Linq查询来选择行,提取XML然后,例如,提取所有 href 标签吗?最终结果将是所有选定行的所有URL的列表。
这是我的尝试,但它没有给我我想要的东西 - 这将是所有选定用户的所有href的列表。我只是得到一个空的IEnumerations列表。
var all = from bm in MYTABLE
select new { name=bm.SPP_USER_ID, xml=(string) bm.SPP_BOOKMARKS_XML};
var docs = from x in all
select XDocument.Parse(x.xml);
var href = from h in docs
select h.Descendants("href");
<小时/> 的解决方案
有2个问题。
- 我想只有在实际需要结果时才会执行查询。随着我从SQL进展到XML查询,生成的查询变成了SQL和XML的混合,因此是不可执行的。我的解决方案是通过将SQL查询转换为结果列表来强制执行结果。这将linq-sql与linq-xml分开。
var docs = from x in all
select XDocument.Parse(x.xml);
var docs2 = docs.ToList(); // force result
- 第二个问题是我忘了将命名空间添加到我的XML查询中。一旦我这样做,我得到了所需的结果
XNamespace ns = "http://acme/bookmarks";
var href = from h in docs2
select h.Descendants(ns + "href");
感谢您的帮助!
答案 0 :(得分:3)
以下是我尝试过的几件事。
我直接查询数据表,如下所示:
var all = from bm in context.MYTABLEs
select new { name = bm.SPP_USER_ID, xml = (string)bm.SPP_BOOKMARKS_XML };
var docs = from x in all
select XDocument.Parse(x.xml);
var href = from h in docs
select h.Descendants("href");
结果是IEnumerables的集合。即对于数据库中的每一行,我得到一个包含所有“href”后代的IEnumerable。所以在这种情况下,我得到了两个结果;第一个结果是包含2个元素的IEnumerable,第二个结果是包含1个元素的IEnumerable。从你的描述来看,这似乎至少接近你想要的。但是,由于查询的结构方式,您可能没有看到您的期望。
请注意,有时候让Visual Studio实际显示这样的查询结果是相当困难的。我发现在经常发布结果枚举之前,我经常需要两次“观察”该项目。
我尝试复制OP中编写的代码,如下所示:
var MYTABLE = (from bm in context.MYTABLEs select bm).ToList();
var all = from bm in MYTABLE
select new { name = bm.SPP_USER_ID, xml = (string)bm.SPP_BOOKMARKS_XML };
var docs = from x in all
select XDocument.Parse(x.xml);
var href = from h in docs
select h.Descendants("href");
当我这样做时,它导致“xml”值被删除,因为它已经是一个XDocument(?),因此将其转换为字符串会导致所有标记被删除。因此,接下来的两个语句因XML分析异常而失败。
答案 1 :(得分:1)
以下是使用您的代码和MYTABLE
的硬编码内容的代码段,它完美无缺(通过LinqPad验证)。也许您的数据库表或MYTABLE
不包含您的想法?你能查看all
的结果吗?
var MYTABLE = new [] {
new {
SPP_USER_ID = "XML-SNIPPET-1",
SPP_BOOKMARKS_XML = @"
<root>
<item>
<href>http://myurl</href>
</item>
<item>
<href>http://myurl2</href>
</item>
</root>
",
},
new {
SPP_USER_ID = "XML-SNIPPET-2",
SPP_BOOKMARKS_XML = @"
<root>
<item>
<href>http://google.com</href>
</item>
</root>
",
}
};
var all = from bm in MYTABLE
select new { name=bm.SPP_USER_ID, xml=(string) bm.SPP_BOOKMARKS_XML};
var docs = from x in all
select XDocument.Parse(x.xml);
var href = from h in docs
select h.Descendants("href");
foreach (var h in href.SelectMany(h => h))
{
Console.WriteLine(h);
}
输出:
<href>http://myurl</href>
<href>http://myurl2</href>
<href>http://google.com</href>
希望这有帮助!