|
Jarod Godel
Utilitarian
Join date: 6 Nov 2003
Posts: 729
|
04-19-2006 16:56
If anyone wants it, I've hacked together a small script that parses basic XML. It's pretty much alphaware -- hence my mentioning it here and not the Scripting Library -- but if anyone is interested if picking art my code, you're welcome it. It's in my LiveJournal.As soon as I figure out how to handle attributes, I'll dump it in the Library. Also, I apologize if this has been done before. I searched for "xml" in both forums, and nothing that looked like a parser showed up.
_____________________
"All designers in SL need to be aware of the fact that there are now quite simple methods of complete texture theft in SL that are impossible to stop..." - Cristiano MidnightAd aspera per intelligentem prohibitus.
|
|
Christopher Omega
Oxymoron
Join date: 28 Mar 2003
Posts: 1,828
|
04-19-2006 17:45
Nice work  I posted an incomplete XML parser a long time ago, modeled off of the Java SAX parser: /54/19/38505/1.htmlIt still has a few bugs that need squishing. I just started it to see if it could be done. The useful applications of the script never really surfaced, so it got put on the backburner. ==Chris
|
|
Eggy Lippmann
Wiktator
Join date: 1 May 2003
Posts: 7,939
|
04-19-2006 18:06
Good, now get it to read XML in OSMP's format and you got yourself an offline editor thing 
|
|
Jarod Godel
Utilitarian
Join date: 6 Nov 2003
Posts: 729
|
04-20-2006 21:44
Okay. I've got it parsing XML with attributes, but it's still just a little prototype. I'm going to crash now and make it more robust and modular tomorrow. For now, here's the protoype code and the XML it's parsing: LSL code...// A very basic XML Parser written in LSL.
// global variables for reading, holding, and handling the initial XML read string xmlFileName = "xml-test"; string xmlBody = ""; integer xmlBodyLine = 0; key xmlBodyKey;
// Chops off the string up to the first, found element // xml - XML string // start - where the llSubStringIndex begins // offset - the length to the right the substring needs to begin string llReadTo(string xml, integer start, integer offset) { integer ReadTo = start + offset; return llGetSubString(xml, ReadTo, -1); }
// Returns the inner text of a node. string llGetNodeText(string xml, string nodeName) { string elStart = "<" + nodeName; string elStop = "</" + nodeName + ">"; integer elCloseTag = llSubStringIndex(xml, elStop); integer elOpenTag = llSubStringIndex(xml, "/>"); // There has to be some kind of closing tag for the parsing to be valid if (elCloseTag != -1 || elOpenTag != -1) { // For: <tag> ... </tag> if (llSubStringIndex(xml, elStart) != -1 && (elCloseTag < elOpenTag || elOpenTag == -1)) { integer nodeStart = llSubStringIndex(xml, elStart) + llStringLength(elStart) + 1; integer nodeStop = llSubStringIndex(xml, elStop) - 1; string nodeText = llGetSubString(xml, nodeStart, nodeStop); return nodeText; }
// For: <tag/> else if (llSubStringIndex(xml, elStart) != -1 && (elCloseTag > elOpenTag || elCloseTag == -1)) { integer nodeStart = llSubStringIndex(xml, elStart) + llStringLength(elStart) + 1; integer nodeStop = llSubStringIndex(xml, "/>") - 1; string nodeText = llGetSubString(xml, nodeStart, nodeStop); return nodeText; } // For: invalid XML else { return ""; } } else { return ""; } }
// Counts the number of nodes in a string integer llCountElements(string xml, string nodeName) { string elStart = "<" + nodeName; integer elStartLen = llStringLength(elStart) + 1; integer nodeCount = 0; while (llSubStringIndex(xml, elStart) != -1) { // Increments node count ++nodeCount; // Chops off the string up to the first, found element xml = llReadTo(xml, llSubStringIndex(xml, elStart), elStartLen); } return nodeCount; }
// Checks for attributes in an element list llGetElementAttributes(string xml) { integer elTagEnd = 0; if (llSubStringIndex(xml, "/>") == -1) { elTagEnd = llSubStringIndex(xml, ">") - 1; } else { if (llSubStringIndex(xml, " />") == -1) { elTagEnd = llSubStringIndex(xml, "/>") - 1; } else { elTagEnd = llSubStringIndex(xml, "/>") - 2; } } xml = llGetSubString(xml, 0, elTagEnd); list attributes = llParseString2List(xml, ["=\"", "\""], []); return attributes; }
// Gets an attribute value, based of an attribute's name, from apaired list string llGetAttributeValue(list attributes, string name) { string value = ""; integer isName = 0; integer isCntr = 0; // isName is switched to 1 when the loop finds a list valuen with the attribute name // in the next iteration, the next list value is assigned to the variable "value" // and isName is reset to 0 while (llList2String(attributes, isCntr)) { if (isName == 1) { value = llList2String(attributes, isCntr); isName = 0; } else { if ((isCntr % 2) == 0) { if (llList2String(attributes, isCntr) == name) { isName = 1; } } } ++isCntr; } return value; }
// Gets a list of nodes list llGetNodeList(string xml, string nodeName) { list nodeList; integer elementCount = llCountElements(xml, nodeName);
// If nodes exist with the XML string, proceed if (elementCount > 0) { integer nodeCntr; for (nodeCntr = 0; nodeCntr < elementCount; nodeCntr++) { string tempText = llGetNodeText(xml, nodeName); nodeList = nodeList + [tempText]; //if (llSubStringIndex(tempText, "<" + nodeName) != -1) //{ // tempText = tempText + "</" + nodeName + ">"; //} //else if (llSubStringIndex(tempText, "</") == -1) //{ // tempText = tempText + "/>"; //} xml = llReadTo(xml, llSubStringIndex(xml, tempText), llStringLength(tempText)); xml = llGetSubString(xml, llSubStringIndex(xml, "<" + nodeName), -1);
} } // If there are no such nodes in the string, return a one element // list with "No nodes" inside. else { nodeList = ["No nodes"]; } return nodeList; }
// This has to be here default { state_entry() { if (xmlBody == "") { state readfile; } else { llSay(0, xmlBody); } }
touch_start(integer total_number) { list spies = llGetNodeList(xmlBody, "spy"); integer spyCntr = 0; while (llList2String(spies, spyCntr) != "") { string xmlTemp = llList2String(spies, spyCntr);
list spyName = llGetElementAttributes(xmlTemp); string nameSpy = llGetAttributeValue(spyName, "name"); if (nameSpy != "Sam") { string color = llGetNodeText(xmlTemp, "suit");
llSay(0, nameSpy + " has a " + color + " uniform."); } else { llSay(0, "I'm not sure what color " + nameSpy + " wears."); } ++spyCntr; } } }
// This simply reads XML from a Notecard. // This can be removed when grabbing information from the web. state readfile { state_entry() { // Makes sure xmlBody is empty xmlBody = ""; // Starts the reading of the notecard xmlBodyKey = llGetNotecardLine(xmlFileName, xmlBodyLine); } dataserver(key query_id, string data) { if (query_id == xmlBodyKey) { // Perform the following while there is text if (data != EOF) { // Removes leading spaces or tabs if (llSubStringIndex(data, "<") > 0) { data = llDeleteSubString(data, 0, (llSubStringIndex(data, "<") - 1)); } // Appends the next line to xmlBody xmlBody = xmlBody + data; // Increments the line counter ++xmlBodyLine; // Reads the next line xmlBodyKey = llGetNotecardLine(xmlFileName, xmlBodyLine); } // If you've gotten to the end of the notecard, go back else { state default; } } } state_exit() { xmlBodyLine = 0; } } XML file named xml-test...<?xml version="1.0" encoding="ISO-8859-1"?> <spies> <spy name="Clover" hair="blond"> <suit>red</suit> </spy> <spy name="Sam" hair="red" /> <spy name="Alex" hair="dark brown"> <suit>yellow</suit> <sex>female</sex> </spy> </spies> As always, my code is in the public domain. Have at it, y'all!
_____________________
"All designers in SL need to be aware of the fact that there are now quite simple methods of complete texture theft in SL that are impossible to stop..." - Cristiano MidnightAd aspera per intelligentem prohibitus.
|