【问题标题】:How to format xml using linq?如何使用 linq 格式化 xml?
【发布时间】:2016-01-08 06:59:22
【问题描述】:

我在这里使用 linq 创建一个 xml,但没有获得所需的格式。这是我的代码

List<string> listvalue = new List<string>();
listvalue.Add("http://example.com/sample.html");
listvalue.Add("http://example.com/new.html");
foreach (string url in listvalue)
{
    var document = new HtmlWeb().Load(url);
    var urls = document.DocumentNode.Descendants("img")
                                    .Select(e => e.GetAttributeValue("src", null))
                                    .Where(s => !String.IsNullOrEmpty(s));

    List<string> asList = urls.ToList();
    GenerateXml(url, asList);                       

}

protected void GenerateXml(string url, List<string> listitems)  //generateXml
{

    XNamespace nsSitemap = "http://www.sitemaps.org/schemas/sitemap/0.9";
    XNamespace nsImage = "http://www.google.com/schemas/sitemap-image/1.1";

    var sitemap = new XDocument(new XDeclaration("1.0", "UTF-8", ""));

    var urlSet = new XElement(nsSitemap + "urlset",
        new XAttribute("xmlns", nsSitemap),
        new XAttribute(XNamespace.Xmlns + "image", nsImage),
        new XElement(nsSitemap + "url",
        new XElement(nsSitemap + "loc", url),
        from urlNode in listitems
        select new XElement(nsImage + "image",
               new XElement(nsImage + "loc", urlNode)
           )));
    sitemap.Add(urlSet);
    sitemap.Save(System.Web.HttpContext.Current.Server.MapPath("/Static/sitemaps/Sitemap-image.xml"));
}

我需要下面的格式

<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">
  <url>
    <loc>http://example.com/sample.html</loc>
    <image:image>
      <image:loc>http://example.com/image.jpg</image:loc>
    </image:image>
    <image:image>
      <image:loc>http://example.com/photo.jpg</image:loc>
    </image:image>
  </url>
<url>
    <loc>http://example.com/new.html</loc>
    <image:image>
      <image:loc>http://example.com/newimage.jpg</image:loc>
    </image:image>
    <image:image>
      <image:loc>http://example.com/newphoto.jpg</image:loc>
    </image:image>
  </url>
</urlset>

但在这里我得到一个 url 标签。如何做到这一点?有什么建议吗?

【问题讨论】:

  • 您在第一段代码中调用GenerateXml inside your loop - 所以最后一次迭代只会使用XML。我怀疑你不想那样...
  • @Jon Skeet:是的,我尝试过使用字典并在循环外生成 xml 中传递字典值。但我不知道如何在 linq 中获取格式
  • @Jon Skeet: Dictionary> myDict = new Dictionary>(); myDict.Add(url, asList);GenerateXml(myDict);

标签: c# xml linq linq-to-xml


【解决方案1】:

听起来这实际上只是想在调用GenerateXml 之前获取所有 URL(从所有源文档中) - 并记住每个 URL 的来源。这很简单:

var sources = new List<string>
{
    "http://example.com/sample.html",
    "http://example.com/new.html"
};
var imagesBySource = sources
    .ToDictionary(source => source,
                  source => new HtmlWeb().Load(url)
                               .DocumentNode.Descendants("img")
                               .Select(e => e.GetAttributeValue("src", null))
                               .Where(s => !String.IsNullOrEmpty(s))
                               .ToList());
GenerateXml(imagesBySource);

然后,您需要将GenerateXml 更改为Dictionary&lt;string, List&lt;string&gt;&gt;。类似(未经测试):

protected void GenerateXml(Dictionary<string, List<string>> imagesByUrl)
{    
    XNamespace nsSitemap = "http://www.sitemaps.org/schemas/sitemap/0.9";
    XNamespace nsImage = "http://www.google.com/schemas/sitemap-image/1.1";

    var sitemap = new XDocument(new XDeclaration("1.0", "UTF-8", ""));

    var urlSet = new XElement(nsSitemap + "urlset",
        new XAttribute("xmlns", nsSitemap),
        new XAttribute(XNamespace.Xmlns + "image", nsImage),
        imagesByUrl.Select(entry => 
            new XElement(nsSitemap + "url",
                new XElement(nsSitemap + "loc", entry.Key),
                from urlNode in entry.Value
                select new XElement(nsImage + "image",
                    new XElement(nsImage + "loc", urlNode)
                )
        )
    );
    sitemap.Add(urlSet);
    var path = HttpContext.Current.Server.MapPath("/Static/sitemaps/Sitemap-image.xml");
    sitemap.Save(path);
}

请注意,这并不能保证源的顺序得以保留。如果您需要,您可能应该创建一个具有UrlImages 属性的类,并将这些属性的列表传递给GenerateXml

【讨论】:

  • source => new HtmlWeb().Load(url) 抛出以下错误无法将 lambda 表达式转换为类型 'System.Collections.Generic.IEqualityComparer' 因为它不是委托类型
  • 所以我使用了 foreach 并且它工作正常 foreach (string url in listvalue) { var document = new HtmlWeb().Load(url); var urls = document.DocumentNode.Descendants("img") .Select(e => e.GetAttributeValue("src", null)) .Where(s => !String.IsNullOrEmpty(s)).ToList(); myDict.Add(url, urls); }
  • @bala3569:应该没问题 - 它应该使用 ToDictionary 的第二个参数作为元素选择器...看看
  • @bala3569:它为我编译,并进行了一些快速更改以使用 XDocument 而不是 HtmlWeb(我以前从未见过)。
猜你喜欢
  • 1970-01-01
  • 2021-02-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多