Skip to content

Commit

Permalink
Merge branch 'xml2src' into develop
Browse files Browse the repository at this point in the history
<no random message>
  • Loading branch information
opussf committed Jan 30, 2024
2 parents 95ecd44 + eb52d54 commit 175c7fd
Show file tree
Hide file tree
Showing 4 changed files with 335 additions and 6 deletions.
8 changes: 8 additions & 0 deletions FEATURE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
## FEATURES

# xml2src

Write a SAX parser to handle the wow.xml files for addons.

http://www.jelks.nu/XML/xmlebnf.html

5 changes: 3 additions & 2 deletions src/scripts/runmany.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ for n in $(seq -f "%05g" 9999 1) ; do
if [ ! "$?" == "0" ]; then
cp target/reports/antout.txt target/reports/antOut$n.txt
#mv $reportFile target/reports/testOut$n.xml
ls -alt target/reports/testOut$n.xml
ls -alt $reportFile
until $(~/Scripts/checkFileChanged.sh ./test/test.lua); do
sleep 1
done
else
ls -alt $reportFile
#ls -alt $reportFile
sleep 1
fi
done
166 changes: 163 additions & 3 deletions src/wowStubs.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1730,10 +1730,170 @@ function C_ChatInfo.SendAddonMessage()
return true
end

-----------------------------------------
-- XML functions
-- A SAX parser takes a content handler, which provides these methods:
-- startDocument() -- called at the start of the Document
-- endDocument() -- called at the end of the Document
-- startElement( tagName, attrs ) -- with each tag start. attrs is a table of attributes and values
-- endElement( tagName ) -- when a tag ends
-- characters( char ) -- for each character not being in a tag
-- The parser calls each of these methods as these events happen.

-- A SAX parser defines a parser (created with makeParser)
-- a Parser has a ContentHandler assigned
-- a Parser also defines these methods:
-- setContentHandler( contentHandler )
-- setFeature() -- prob not going to implement
-- parse( text )
-- parse( file )

-- https://www.w3schools.com/xml/xml_elements.asp
-- https://www.w3schools.com/xml/xml_syntax.asp


contentHandler = {}
-- normally the contentHandler is an object, where data structures are created in the new object.
function contentHandler.startDocument( this )
end
function contentHandler.endDocument( this )
end
function contentHandler.startElement( this, tagName, attrs )
end
function contentHandler.endElement( this, tagName )
end
function contentHandler.characters( this, char )
end

saxParser = {}
-- SAX Parser
-- interface
function saxParser.makeParser()
-- make a parser. This is probably intended to be a factory function
return saxParser
end
function saxParser.setContentHandler( contentHandlerIn )
-- takes a table
saxParser.contentHandler = contentHandlerIn
end
function saxParser.setFeature()
-- research this
end
function saxParser.parse( fileIn )
f = io.open( fileIn, "r" )
if f then fileIn = f:read( "*all" ) end -- read the contents of the file

-- call the startDocument method for the given contentHandler
if saxParser.contentHandler and saxParser.contentHandler.startDocument then
saxParser.contentHandler:startDocument()
end

-- loop through each char
State = {
Outside = { 0 }, -- outside of a tag
ElementName = { 1 }, -- When to parse for a name
InElement = { 2 }, -- In the element
}
currentState = State.Outside
elementDepth = {} -- table of current element depth
elementName = ""
chars = ""

while( #fileIn > 0 ) do
-- print( currentState[1].."\t"..#fileIn, "fileIn: "..string.sub( fileIn, 1, 60 ) )
c = string.sub( fileIn, 1, 1 )
n = string.sub( fileIn, 2, 2 )
handled = false
if currentState == State.Outside then
if c == "<" then
if n == "?" then
local endProlog = string.find( fileIn, "?>" )
if endProlog then
fileIn = string.sub( fileIn, endProlog+2 )
end
elseif n == "!" then
local endComment = string.find( fileIn, "-->" )
if endComment then
fileIn = string.sub( fileIn, endComment+3 )
end
else
currentState = State.ElementName
elementName = ""
fileIn = string.sub( fileIn, 2 )
end
else
saxParser.contentHandler:characters( c )
fileIn = string.sub( fileIn, 2 )
end
elseif currentState == State.ElementName then
tagStart, tagEnd, tagName = string.find( fileIn, "^([%a_][%a%d-_.]*)" )
if tagStart then
elementName = tagName
attributes = {}
currentState = State.InElement
fileIn = string.sub( fileIn, tagEnd + 1 )
end
tagStart, tagEnd, tagName = string.find( fileIn, "^/([%a_][%a%d-_.]*)" )
if tagStart then
elementName = tagName
-- print( "Fire endElement( "..tagName.." )" )
depthElement = table.remove( elementDepth )
saxParser.contentHandler:endElement( tagName )
if depthElement ~= elementName then
fail( "ERROR: Closing "..elementName.." is not the expected element to close; "..depthElement.." is expected." )
end
currentState = State.Outside
fileIn = string.sub( fileIn, tagEnd + 2 )
end
elseif currentState == State.InElement then
attribStart, attribEnd, key, value = string.find( fileIn, "^%s*(%S+)%s*=%s*[\"\'](.-)[\"\']" )
if attribStart then
attributes[key] = value
fileIn = string.sub( fileIn, attribEnd+1 )
elseif c == " " then
fileIn = string.sub( fileIn, 2 )
elseif c == ">" or n == ">" then
-- print( "Fire startElement( "..elementName.." )" )
-- print( "\twith attributes: ")
-- for k,v in pairs( attributes ) do
-- print( "\t\t"..k..":="..v )
-- end
table.insert( elementDepth, elementName )
saxParser.contentHandler:startElement( elementName, attributes )
currentState = State.Outside
if c == "/" and n == ">" then
-- print( "Fire endElement( "..elementName.." )" )
depthElement = table.remove( elementDepth )
saxParser.contentHandler:endElement( elementName )
if depthElement ~= elementName then
fail( "ERROR: Closing "..elementName.." is not the expected element to close; "..depthElement.." is expected." )
end
currentState = State.Outside
end
fileIn = string.sub( fileIn, (n==">" and 3 or 2) )
end
end
-- print( "elementDepth: "..table.concat( elementDepth, "\t" ) )
end

-- call the endDocument method for the given contentHandler
if saxParser.contentHandler and saxParser.contentHandler.endDocument then
saxParser.contentHandler:endDocument()
end
end
function ParseXML( xmlFile )
print("parse: "..xmlFile )
ch = contentHandler
ch.startElement = function( self, tagIn, attribs )
if _G["Create"..tagIn] then
if attribs.name then
_G[attribs.name] = _G["Create"..tagIn]( attribs.name )
_G[attribs.name].framename = attribs.name
else
fail("A "..tagIn.." needs a name")
end
end
end
parser = saxParser.makeParser()
parser.setContentHandler( ch )
parser.parse( xmlFile )
end

-----------------------------------------
Expand Down
162 changes: 161 additions & 1 deletion test/test.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1062,13 +1062,173 @@ function CreateFile( filename, contents )
return tocFile
end
function test.testTOC_()
CreateFile( "test.xml", "<Ui>\n</Ui>\n" )
CreateFile( "test.xml", "<Ui>\n<Frame name=\"topFrame\"></Frame></Ui>\n" )
CreateFile( "test.lua", "print(\"hi\")\n")
generatedFile = CreateFile( "test.toc", "test.lua\ntest.xml\n" )
ParseTOC( generatedFile )
end


----- Sax tests
function test.before_testContentHandler()
originalContentHandler = {}
for k,v in pairs( contentHandler ) do
originalContentHandler[k] = v
end
end
function test.after_testContentHandler()
contentHandler = {}
for k,v in pairs( originalContentHandler ) do
contentHandler[k] = v
end
end
function test.testContentHandler_hasStartDocument()
test.before_testContentHandler()
assertTrue( contentHandler.startDocument )
test.after_testContentHandler()
end
function test.testContentHandler_hasEndDocument()
test.before_testContentHandler()
assertTrue( contentHandler.endDocument )
test.after_testContentHandler()
end
function test.testContentHandler_hasStartElement()
test.before_testContentHandler()
assertTrue( contentHandler.startElement )
test.after_testContentHandler()
end
function test.testContentHandler_hasEndElement()
test.before_testContentHandler()
assertTrue( contentHandler.endElement )
test.after_testContentHandler()
end
function test.testContentHandler_hasCharacters()
test.before_testContentHandler()
assertTrue( contentHandler.characters )
test.after_testContentHandler()
end


function test.before_testSax()
originalContentHandler = {}
for k,v in pairs( contentHandler ) do
originalContentHandler[k] = v
end
end
function test.after_testSax()
contentHandler = {}
for k,v in pairs( originalContentHandler ) do
contentHandler[k] = v
end
end
function test.testSAX_MakeParser()
test.before_testSax()
assertTrue( saxParser.makeParser() )
test.after_testSax()
end
function test.testSAX_setContentHandler()
test.before_testSax()
ch = contentHandler
parser = saxParser.makeParser()
parser.setContentHandler( ch )
assertTrue( parser.contentHandler )
--ch = nil
--parser = nil
test.after_testSax()
end
function test.notestSAX_Parse_StartDocument_TextIn()
test.before_testSax()
ch = contentHandler
ch.startDocument = function( this ) this.started = true; end
parser = saxParser.makeParser()
parser.setContentHandler( ch )
parser.parse( "<xml/>" )
assertTrue( ch.started )
end
function test.notestSAX_Parse_StartDocument_FileIn()
test.before_testSax()
ch = contentHandler
ch.startDocument = function( this ) this.started = true; end
parser = saxParser.makeParser()
parser.setContentHandler( ch )
parser.parse( "../build.xml" )
assertTrue( ch.started )
end
function test.notestSAX_Parse_StartDocument_NotGiven_TextIn()
test.before_testSax()
ch = contentHandler
ch.startDocument = nil
parser = saxParser.makeParser()
parser.setContentHandler( ch )
parser.parse( "<xml/>" )
assertIsNil( ch.started )
end
function test.testSAX_Parse_EndDocument_TextIn()
test.before_testSax()
ch = contentHandler
ch.endDocument = function( this ) this.ended = true; end
parser = saxParser.makeParser()
parser.setContentHandler( ch )
parser.parse( "<xml/>" )
assertTrue( ch.ended )
end
function test.testSAX_Parse_StartElement_TextIn()
-- affirm that the startElement method is called
test.before_testSax()
ch = contentHandler
ch.startElement = function( this, tagIn, attribs ) this.tagIn = tagIn; end
parser = saxParser.makeParser()
parser.setContentHandler( ch )
parser.parse( "<xml/>" )
assertEquals( "xml", ch.tagIn )
end
function test.testSAX_Parse_StartElementAttribs_TextIn()
-- affirm that the startElement method is called
test.before_testSax()
ch = contentHandler
ch.startElement = function( this, tagIn, attribs ) this.version = attribs["version"]; end
parser = saxParser.makeParser()
parser.setContentHandler( ch )
parser.parse( "<xml version=\"1\" />" )
assertEquals( "1", ch.version )
end
function test.testSAX_Parse_StartElementAttribs_TextIn2()
-- affirm that the startElement method is called
test.before_testSax()
ch = contentHandler
ch.startElement = function( this, tagIn, attribs ) this.version = attribs["version"]; end
parser = saxParser.makeParser()
parser.setContentHandler( ch )
parser.parse( "<xml version=\"2\"></xml>" )
assertEquals( "2", ch.version )
end
function test.testSax_Parse_StartElement_Prolog()
test.before_testSax()
ch = contentHandler
ch.startElement = function( this, tagIn, attribs ) this.version = attribs["version"]; end
parser = saxParser.makeParser()
parser.setContentHandler( ch )
parser.parse( "<?xml version=\"1.0\" encoding=\"UTF-8\"?><xml version=\"3\"></xml>" )
assertEquals( "3", ch.version )
end
function test.testSax_Parse_StartElement_Comment()
test.before_testSax()
ch = contentHandler
ch.startElement = function( this, tagIn, attribs ) this.version = attribs["version"]; end
parser = saxParser.makeParser()
parser.setContentHandler( ch )
parser.parse( "<!-- xml version=\"1.0\" encoding=\"UTF-8\" --><xml version=\"4\"></xml>" )
assertEquals( "4", ch.version )
end
function test.testSax_Parse_NestedElements()
test.before_testSax()
ch = contentHandler
ch.startElement = function( this, tagIn, attribs ) this.broken = attribs["broken"]; end
parser = saxParser.makeParser()
parser.setContentHandler( ch )
parser.parse( "<!-- xml version=\"1.0\" encoding=\"UTF-8\" --><xml version=\"4\"><bleh broken=\"5\"></bleh></xml>" )
assertEquals( "5", ch.broken )
end
----------------------------------
-- Run the tests
----------------------------------
Expand Down

0 comments on commit 175c7fd

Please sign in to comment.