tadija / AEXML

Swift minion for simple and lightweight XML parsing
MIT License
1.01k stars 200 forks source link

Support for DTDs? #168

Open Vithanco opened 4 years ago

Vithanco commented 4 years ago

I would like to specify the correct DTD for the XML file used. How should I do this? Right now I consider enhancing AEXMLOptions.DocumentHeader with 3 additional optional values which would allow specifying the correct settings for the DTD (see eg. https://xmlwriter.net/xml_guide/doctype_declaration.shtml). Any better idea?

Many thanks in advance!

Vithanco commented 4 years ago

Maybe I should initiate the document with a root element and a DTD already included?

tadija commented 4 years ago

Hi @TheMadOne, I think that extending AEXMLOptions with another subtype for this purpose is a good idea (rather than extending existing DocumentHeader type). I'm not sure if this would affect parsing in some unexpected way, but if not that it should be a simple change. Creating the document with a custom root element is also a valid option I guess.

Vithanco commented 4 years ago

I looked into this. I created the document like this: 

svg = try AEXMLDocument(xml: """        
<?xml version="1.0" encoding="UTF-8"?>        
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"         
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">        
<svg version="1.1" xmlns="http://www.w3.org/2000/svg">        
</svg>        
""")

however, when I save this I get only this:

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"></svg>

AEXMLOptions isn't ready for inheritance, since it is a struct and you didn't use a protocol. However, I assume you are open for me to change this?. I will send you a pull request.

marcuswu0814 commented 3 years ago

I facing the same issue, through some code trace, AEXMLOptions currently not possible to extend other headers.

As a work around, I create a new class inherit from AEXMLDocument and override the xml computed property like this:

class PlistDocument: AEXMLDocument {

    override var xml: String {
        var xml =  "\(options.documentHeader.xmlString)\n"
        let plistDTD = """
        <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n
        """
        xml += plistDTD
        xml += root.xml
        return xml
    }

}

It work expected. Any better solution for this requirement or if need some enhancement for AEXMLOptions (maybe some refactor with DI), feel free to tell me and I will make a PR when I get free time. 😅

===

P.S.

Maybe somebody would say why not using PropertyListSerialization to make Plist file in my case.

I have no idea how to handle NSNumber and wrong precision of floating number in the black box of PropertyListSerialization. 🤦‍♂️