Pradyot
Pradyot

Reputation: 3059

xml validation(DTD) using lxml(python)

There is a brief explanation of validation based on XML here. I am trying to parse an XML file that refers to nested DTD's ie: XML file refers to a DTD, which refers to other DTD's.

The error I get is Namespace prefix SomeNameSpace on Config is not defined. All I am trying to do is parse the xml using etree.parse which is an API on lxml. My question is:

  1. Can I just turn off the validation (I am assuming the xml is correct)?
  2. How exactly can i provide lxml all the nested DTDs , so it doesn't complain about any of the tags?

I see similar questions, but nothing that answers this question.

Upvotes: 0

Views: 1137

Answers (2)

Jeremiah
Jeremiah

Reputation: 1455

A while back I tried to do something similar and wasn't able to find a solution. I finally wrote the script below which opens the XML file and looks for a DTD using a regex. It also has an override to take the DTD path on the command line, which was a requirement I had.

If lxml handles nested DTDs then the code below should work for you.

To be honest I thought it was a bit of a hack to read the file myself, but it was the only way I found.

import re
import sys
import os.path
import codecs
from lxml import etree

def main(args):
    if len(args)<1:
        print("Not enough arguments given.  Expected:")
        print("\tvalidatexml <xml file name> [<dtd file name>]\n")
        exit(1)

    dtdRe = re.compile('.*<!DOCTYPE .* ["\'](.*\.dtd)["\']>.*')
    theDtd = None
    inFile = args[0]
    fdir = os.path.abspath(os.path.dirname(inFile))
    if len(args)==2:
        theDtd = os.path.abspath(args[1])
    else:
        with codecs.open(args[0], 'r', 'utf-8') as inf:
            for ln in inf:
                mtch = dtdRe.match(ln)
                if mtch:
                    if os.path.isabs(mtch.group(1)):
                        theDtd = mtch.group(1)
                    else:
                        theDtd = os.path.abspath(fdir + '/' + mtch.group(1))
                    break
    if theDtd is None:
        print("No DTD specified!")
        exit(2)

    if not os.path.exists(theDtd):
        print("The DTD ({}) does not exist!".format(theDtd))
        exit(3)

    print('Using DTD:', theDtd)

    parser = etree.XMLParser(dtd_validation=True)
    dtd = etree.DTD(open(theDtd))
    tree = etree.parse(args[0])

    valid = dtd.validate(tree)
    if (valid):
        print("XML was valid!")

    else:
        print("XML was not valid:")
        print(dtd.error_log.filter_from_errors())


if __name__ == '__main__':
    main(sys.argv[1:])

Upvotes: 1

Abbasov Alexander
Abbasov Alexander

Reputation: 1938

Can you try parse by Beautiful Soup? Errors still is exists?

Upvotes: 0

Related Questions