在 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");
我想做的就是获取我的 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");