bugfixes for unicode; xmlparser; htmlparser; scanner
This commit is contained in:
parent
64da2f1681
commit
6bc16904ed
18 changed files with 226 additions and 74 deletions
|
|
@ -14,9 +14,34 @@ import xmldom, os, streams, parsexml, strutils
|
|||
#XMLDom's Parser - Turns XML into a Document
|
||||
|
||||
type
|
||||
#Parsing errors
|
||||
# Parsing errors
|
||||
EMismatchedTag* = object of E_Base ## Raised when a tag is not properly closed
|
||||
EParserError* = object of E_Base ## Raised when an unexpected XML Parser event occurs
|
||||
|
||||
# For namespaces
|
||||
xmlnsAttr = tuple[name, value: string, ownerElement: PElement]
|
||||
|
||||
var nsList: seq[xmlnsAttr] = @[] # Used for storing namespaces
|
||||
|
||||
proc getNS(prefix: string): string =
|
||||
var defaultNS: seq[string] = @[]
|
||||
|
||||
for key, value, tag in items(nsList):
|
||||
if ":" in key:
|
||||
if key.split(':')[1] == prefix:
|
||||
return value
|
||||
|
||||
if key == "xmlns":
|
||||
defaultNS.add(value)
|
||||
|
||||
# Don't return the default namespaces
|
||||
# in the loop, because then they would have a precedence
|
||||
# over normal namespaces
|
||||
if defaultNS.len() > 0:
|
||||
return defaultNS[0] # Return the first found default namespace
|
||||
# if none are specified for this prefix
|
||||
|
||||
return ""
|
||||
|
||||
proc parseText(x: var TXmlParser, doc: var PDocument): PText =
|
||||
result = doc.createTextNode(x.charData())
|
||||
|
|
@ -28,24 +53,33 @@ proc parseElement(x: var TXmlParser, doc: var PDocument): PElement =
|
|||
case x.kind()
|
||||
of xmlEof:
|
||||
break
|
||||
of xmlElementStart:
|
||||
of xmlElementStart, xmlElementOpen:
|
||||
if n.tagName() != "":
|
||||
n.appendChild(parseElement(x, doc))
|
||||
else:
|
||||
n = doc.createElement(x.elementName)
|
||||
of xmlElementOpen:
|
||||
if n.tagName() != "":
|
||||
n.appendChild(parseElement(x, doc))
|
||||
else:
|
||||
if x.elementName.contains(':'):
|
||||
#TODO: NamespaceURI
|
||||
n = doc.createElementNS("nil", x.elementName)
|
||||
else:
|
||||
n = doc.createElement(x.elementName)
|
||||
n = doc.createElementNS("", x.elementName)
|
||||
|
||||
of xmlElementEnd:
|
||||
if x.elementName == n.nodeName:
|
||||
# n.normalize() # Remove any whitespace etc.
|
||||
|
||||
var ns: string
|
||||
if x.elementName.contains(':'):
|
||||
ns = getNS(x.elementName.split(':')[0])
|
||||
else:
|
||||
ns = getNS("")
|
||||
|
||||
n.namespaceURI = ns
|
||||
|
||||
# Remove any namespaces this element declared
|
||||
var count = 0 # Variable which keeps the index
|
||||
# We need to edit it..
|
||||
for i in low(nsList)..len(nsList)-1:
|
||||
if nsList[count][2] == n:
|
||||
nsList.delete(count)
|
||||
dec(count)
|
||||
inc(count)
|
||||
|
||||
return n
|
||||
else: #The wrong element is ended
|
||||
raise newException(EMismatchedTag, "Mismatched tag at line " &
|
||||
|
|
@ -54,11 +88,15 @@ proc parseElement(x: var TXmlParser, doc: var PDocument): PElement =
|
|||
of xmlCharData:
|
||||
n.appendChild(parseText(x, doc))
|
||||
of xmlAttribute:
|
||||
if x.attrKey == "xmlns" or x.attrKey.startsWith("xmlns:"):
|
||||
nsList.add((x.attrKey, x.attrValue, n))
|
||||
|
||||
if x.attrKey.contains(':'):
|
||||
#TODO: NamespaceURI
|
||||
n.setAttributeNS("nil", x.attrKey, x.attrValue)
|
||||
var ns = getNS(x.attrKey)
|
||||
n.setAttributeNS(ns, x.attrKey, x.attrValue)
|
||||
else:
|
||||
n.setAttribute(x.attrKey, x.attrValue)
|
||||
|
||||
of xmlCData:
|
||||
n.appendChild(doc.createCDATASection(x.charData()))
|
||||
of xmlComment:
|
||||
|
|
@ -75,16 +113,13 @@ proc parseElement(x: var TXmlParser, doc: var PDocument): PElement =
|
|||
|
||||
raise newException(EMismatchedTag,
|
||||
"Mismatched tag at line " & $x.getLine() & " column " & $x.getColumn)
|
||||
|
||||
proc loadXML*(path: string): PDocument =
|
||||
## Loads and parses XML from file specified by ``path``, and returns
|
||||
|
||||
proc loadXMLStream*(stream: PStream): PDocument =
|
||||
## Loads and parses XML from a stream specified by ``stream``, and returns
|
||||
## a ``PDocument``
|
||||
|
||||
var s = newFileStream(path, fmRead)
|
||||
if s == nil: raise newException(EIO, "Unable to read file " & path)
|
||||
|
||||
var x: TXmlParser
|
||||
open(x, s, path, {reportComments})
|
||||
open(x, stream, nil, {reportComments})
|
||||
|
||||
var XmlDoc: PDocument
|
||||
var DOM: PDOMImplementation = getDOM()
|
||||
|
|
@ -102,10 +137,32 @@ proc loadXML*(path: string): PDocument =
|
|||
else:
|
||||
raise newException(EParserError, "Unexpected XML Parser event")
|
||||
|
||||
close(x)
|
||||
return XmlDoc
|
||||
|
||||
proc loadXML*(xml: string): PDocument =
|
||||
## Loads and parses XML from a string specified by ``xml``, and returns
|
||||
## a ``PDocument``
|
||||
var s = newStringStream(xml)
|
||||
return loadXMLStream(s)
|
||||
|
||||
|
||||
proc loadXMLFile*(path: string): PDocument =
|
||||
## Loads and parses XML from a file specified by ``path``, and returns
|
||||
## a ``PDocument``
|
||||
|
||||
var s = newFileStream(path, fmRead)
|
||||
if s == nil: raise newException(EIO, "Unable to read file " & path)
|
||||
return loadXMLStream(s)
|
||||
|
||||
|
||||
when isMainModule:
|
||||
var xml = loadXML(r"C:\Users\Dominik\Desktop\Code\Nimrod\xmldom\test.xml")
|
||||
echo($xml)
|
||||
var xml = loadXMLFile(r"C:\Users\Dominik\Desktop\Code\Nimrod\xmldom\test.xml")
|
||||
#echo(xml.getElementsByTagName("m:test2")[0].namespaceURI)
|
||||
#echo(xml.getElementsByTagName("bla:test")[0].namespaceURI)
|
||||
#echo(xml.getElementsByTagName("test")[0].namespaceURI)
|
||||
for i in items(xml.getElementsByTagName("*")):
|
||||
if i.namespaceURI != nil:
|
||||
echo(i.nodeName, "=", i.namespaceURI)
|
||||
|
||||
|
||||
echo($xml)
|
||||
Loading…
Add table
Add a link
Reference in a new issue