02. juni 2006 - 15:27
Der er
15 kommentarer og 1 løsning
Recursive method vil ikke virke
Hejsa Jeg har et problem med denne her rekursive funktion, som looper et XML dokument igennem, og generere en htmlstring med tilsvarede <ul><li> elementer, afhæning af dybden. private string GenerateMenu(XmlNodeList menuNodes,string htmlMenu) { htmlMenu += "<ul>\n"; for(int i=0;i<menuNodes.Count;i++) { if(menuNodes[i].ChildNodes.Item(0).HasChildNodes) { XmlNode subMenuNode = menuNodes[i].ChildNodes.Item(0); XmlNodeList subMenuNodes = subMenuNode.ChildNodes; htmlMenu += "<li>"; htmlMenu += menuNodes[i].Attributes[0].Value + "\n"; htmlMenu += GenerateMenu(subMenuNodes,htmlMenu); htmlMenu += "</li>\n"; } else { htmlMenu += "<li>" + menuNodes[i].ChildNodes.Item(0).InnerText + "</li>\n"; } } htmlMenu += "</ul>"; return htmlMenu; } Lige nu får jeg følgende fejl: [NullReferenceException: Object reference not set to an instance of an object.] MenuView.GenerateMenu(XmlNodeList menuNodes, String htmlMenu) +73 MenuView.GenerateMenu(XmlNodeList menuNodes, String htmlMenu) +201 MenuView.Page_Load(Object sender, EventArgs e) +65 System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) +13 System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +45 System.Web.UI.Control.OnLoad(EventArgs e) +98 System.Web.UI.Control.LoadRecursive() +71 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +4308 Og den fejl siger mig ikke så meget, nogen som kan se fejlen?
Annonceindlæg tema
Offentlig digitalisering
Fra effektivisering til digital suverænitet. Hvordan skaber det offentlige en digital fremtid med AI, sikkerhed og kontrol i centrum?
Og den aktiveres ved: XmlDocument menuXML = new XmlDocument(); menuXML.Load("c:/IIS/hemmelig/menu/da.xml"); XmlNodeList menuNodes = menuXML.DocumentElement.ChildNodes; test.Text = GenerateMenu(menuNodes,"");
Du skal nok rette: if(menuNodes[i].ChildNodes.Item(0).HasChildNodes) - til: if(menuNodes[i].HasChildNodes)
nej :-) Fordi at C# betragter "foobar" i <m>foobar</m> som en childnode, og jeg ønsker kun at check hvis det var <m><m>foo</m><m>bar</m></m>
fejlmeddelsen er forresten debugget det at være her: htmlMenu += GenerateMenu(subMenuNodes,htmlMenu);
Den linje kan nu ikke generere den fejl. Fejlen ligger inden i selve funktionen. Og jo, den stemmer ganske pænt med at du muligvis begynder at forsøge at bruge en nodes children selv om der ikke er nogen: Hvis "menuNodes[i].HasChildNodes" er false, så vil "menuNodes[i].ChildNodes.Item(0)" give en nullpointer-exception.
ja, men hvis det er tilfældet, er problemet jo først når jeg looper subnodes, hvis jeg undlader linjen "htmlMenu += GenerateMenu(subMenuNodes,htmlMenu);" så looper den fint det overordnet set af data igennem, uden fejl.
Det skyldes sikkert at dit overordnede niveau jo *har* child-noder. Grunden til at den fejler når du tilføjer det rekursive kald, er at den så på et eller andet tidspunkt kommer så langt ud i dine noder, at den kommer til en node som ikke har child-noder. Og der fejler den så.
Her er XML delen: <?xml version="1.0" encoding="iso-8859-1"?> <menu lang="en"> <m>Frontpage</m> <m label="Products"> <m>Telephoning</m> <m>Broadband / ADSL</m> <m>Mobile Telephoning</m> <m label="Internet"> <m>Wireless</m> </m> <m>IP Telephoning</m> </m> <m label="Prices"> <m>Private</m> <m>Buisnesss</m> </m> <m>Order</m> <m label="Support"> <m>FAQ</m> <m>Support</m> <m>Performance</m> <m>Conditions</m> </m> <m>Contact</m> <m>Clientlogin</m> </menu>
Så hvordan får vi nu rette kode, så det virker ?
02. juni 2006 - 17:21
#10
jeg valgte at omskrive en hel del proev foelgende: using System; using System.Xml; namespace E { public class MainClass { private const string INDENT = " "; private static string GenerateMenu(XmlNode node, string indent) { string htmlMenu = ""; if(node.HasChildNodes && node.FirstChild.NodeType != XmlNodeType.Text) { if(indent.Length > 0) { htmlMenu += (indent + "<li>\n"); } if(node.Attributes.Count > 0) { htmlMenu += (indent + node.Attributes[0].Value + "\n"); } htmlMenu += (indent + "<ul>\n"); foreach(XmlNode newnode in node.ChildNodes) { htmlMenu += GenerateMenu(newnode, indent + INDENT); } htmlMenu += (indent + "</ul>\n"); if(indent.Length > 0) { htmlMenu += (indent + "</li>\n"); } } else { htmlMenu += (indent + "<li>" + node.InnerText + "</li>\n"); } return htmlMenu; } public static void Main(string[] args) { XmlDocument menuXML = new XmlDocument(); menuXML.Load(@"c:\test.xml"); Console.WriteLine(GenerateMenu(menuXML.DocumentElement, "")); } } }
02. juni 2006 - 18:49
#11
Nice. node.FirstChild.NodeType != XmlNodeType.Text var lige hvad jeg stod og manglede, og den foreach(x in) er også en del smartere. Mange tak. Points går til arne_v :-)
02. juni 2006 - 18:57
#12
svar
02. juni 2006 - 18:58
#13
Et sidste spørgsmål vis nogen skulle vide det. Hvilket asp.net element bør jeg binde min html string til ?
02. juni 2006 - 19:13
#14
Ingen anelse. Jeg tror slet ikke at det er den rigtige ASP.NET maade, men jeg kan ikke umiddelbart udpege et alternativ.
02. juni 2006 - 23:32
#15
Mit bud: private const string INDENT = " "; private static string GenerateMenu(XmlNodeList menuNodes, string indent) { string htmlMenu = indent + "<ul>\n"; string newIndent = indent + INDENT; for (int i = 0; i < menuNodes.Count; i++) { htmlMenu += newIndent + "<li>\n"; if (menuNodes[i].Attributes.Count > 0) { htmlMenu += newIndent + INDENT + menuNodes[i].Attributes["label"].Value + "\n"; htmlMenu += GenerateMenu(menuNodes[i].ChildNodes, newIndent); } else { htmlMenu += newIndent + INDENT + menuNodes[i].InnerText + "\n"; } htmlMenu += newIndent + "</li>\n"; } htmlMenu += indent + "</ul>\n"; return htmlMenu; }
09. juni 2006 - 09:11
#16
Et råd: lad være med at bruge rekursive funktioner, de bruger alt for meget CPU i forhold til at bruge f.eks. while loops. Men de er selvfølgelig sjove at lave.
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.