【问题标题】:Traverse XML Style Sitemap File in C#在 C# 中遍历 XML 样式的站点地图文件
【发布时间】:2015-04-10 21:38:31
【问题描述】:

我要做的就是取出我的 MySite.sitemap 文件,从中吸出所有节点,然后将其打印到文件中。长期目标是获取每个节点并查看它是父节点还是子节点。

MySite.sitemap

<?xml version="1.0" encoding="utf-8"?>
<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0">
    <siteMapNode title="Grand Parent 1" roles="Grand Parent Role" description="A simple description that I might want to write to the text file.">
        <siteMapNode title="Parent" description="" roles="Parent Role">
            <siteMapNode title="Child 1" url="linkToPage.aspx" description="A short description." />
            <siteMapNode title="Child 2" url="linkToPage2.aspx" description="Another short description." />
        </siteMapNode>
        <siteMapNode title="Parent 2" description="" roles="Parent Role" />
            <siteMapNode title="Child 3" url="linkToPage3.aspx" description"A short description." />
            <siteMapNode title="Child 4" url="linkToPage4.aspx" description="Another short description." />
        </siteMapNode>
    </siteMapNode>
</siteMap>

C#

StreamWriter file = new StreamWriter("debugFile.txt");

file.WriteLine("Sitemap File: " + pathToSiteMapFile + siteMapFile);
XmlDocument xml = new XmlDocument();
xml.Load(pathToSiteMapFile + siteMapFile);
XmlNamespaceManager manager = new XmlNamespaceManager(xml.NameTable);
//manager.AddNamespace("s", xml.DocumentElement.NamespaceURI);
XmlNodeList nodeList = xml.SelectNodes("/siteMap/siteMapNode", manager);

foreach (XmlNode node in nodeList) {
    file.WriteLine("Trying to loop through xnlist...\r\n");
    file.WriteLine("Node: " + node.InnerText + "\r\n");
}

foreach (string str in testPages) {
    file.Write("File: " + str + "\r\n");
}
file.WriteLine("The foreach loop should have wrote all the nodes in here.\r\n");
file.Close();

如果有人能帮我弄清楚下一个问题是,一旦我枚举了每个节点,我是否能够进入每个节点并根据每个节点内的内容执行逻辑? IE 节点 a 具有节点 b 没有的角色。

【问题讨论】:

  • 您想要所有的siteMapNode 节点还是只想要顶级节点?
  • siteMapNode 目前为止,但最好是全部。

标签: c# xml sitemap


【解决方案1】:

要使用SelectNodes,您需要明确指定命名空间(不是 XML 文件中的命名空间前缀)和名称:

        XmlNamespaceManager ns = new XmlNamespaceManager(xml.NameTable);
        ns.AddNamespace("myPrefix", @"http://schemas.microsoft.com/AspNet/SiteMap-File-1.0");

        var topNodes = xml.SelectNodes("/myPrefix:siteMap/myPrefix:siteMapNode", ns);
        var allNodes = xml.SelectNodes("//myPrefix:siteMapNode", ns);

这里查询字符串中的文本"myPrefix" 是对通过调用ns.AddNamespace("myPrefix", ...) 添加的命名空间的查找。这只是对您自己创建的本地表的查找。

要将所有节点输出到文件,您可以执行以下操作:

        foreach (XmlNode node in allNodes)
        {
            var text = new string(' ', node.AncestorsAndSelf().Count() - 1) + "Node: " + string.Join(", ", node.Attributes.Cast<XmlAttribute>().Select(a => a.Name + ": " + a.Value).ToArray());
            file.WriteLine(text);
        }

鉴于extension method

public static class XmlNodeExtensions
{
    public static IEnumerable<XmlNode> AncestorsAndSelf(this XmlNode node)
    {
        for (; node != null; node = node.ParentNode)
            yield return node;
    }
}

产生如下输出:

 Node: title: Grand Parent 1, roles: Grand Parent Role, description: A simple description that I might want to write to the text file.
   Node: title: Parent, description: , roles: Parent Role
    Node: title: Child 1, url: linkToPage.aspx, description: A short description.
    Node: title: Child 2, url: linkToPage2.aspx, description: Another short description.
   Node: title: Parent 2, description: , roles: Parent Role
    Node: title: Child 3, url: linkToPage3.aspx, description: A short description.
    Node: title: Child 4, url: linkToPage4.aspx, description: Another short description.

顺便说一句,使用Linq-to-XML 的初始查询看起来要简单得多:

        var xDoc = XDocument.Load(pathToSiteMapFile + siteMapFile);

        var topElements = xDoc.Root.Elements(xDoc.Root.Name.Namespace + "siteMapNode");
        var allElements = xDoc.Root.Descendants(xDoc.Root.Name.Namespace + "siteMapNode");

【讨论】:

  • 有点尴尬但是,我怎么知道我的前缀是什么?或者这几乎是我想要的?我可以像您的示例一样输入“myPrefix”,它会起作用...?
  • @gh0st - 使用您想要的任何前缀,只要确保您传递给AddNamespace 的前缀与您在查询字符串中使用的前缀相同。我怀疑微软设计了它的 API,所以我们不能硬编码 XML 文件中的前缀,所以必须使用实际的命名空间。
  • 根据您的建议,循环至少现在可以运行。但仍然没有打印出node.InnerText。我希望至少能够从节点中获取 URL。
  • @gh0st - 这些节点没有文本值;只是属性和孩子。您想在文件中看到什么?
  • 我可以将titleurl 从中提取出来吗?例如,在我最初的问题中,我有一个带有title="Child 1" 的节点,我可以提取它并将其打印到我的调试文件中吗?还是 URL 字段,还是全部?
猜你喜欢
  • 2022-12-06
  • 2019-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-18
  • 1970-01-01
相关资源
最近更新 更多