在 C# 中遍历 XML 样式站点地图文件

Traverse XML Style Sitemap File in C#

我想做的就是获取我的 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 没有的角色。

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

        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", ...) 添加的名称空间的查找。这只是对您自己创建的本地 table 的查找。

要将所有节点输出到一个文件,您可以这样做:

        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");