Data Modeling Nightmare: XML, HTML, and Markdown
A developer explains the difficulty he had in dealing with markup languages while performing data scraping and data modeling using Python.
Join the DZone community and get the full member experience.Join For Free
here's a particularly tangled and difficult problem. it arises because i have another blog. specifically this: team red cruising . and it's an unholy mess.
there are two important features of the team red cruising blog.
- it's managed with an off-line editor(s) so i can write posts from the boat and then upload them when i get connectivity. welcome to being a technomad — i don't always have a web-based blog editor available.
- it was actually created with two different off-line editors over a period of years: iweb and sandvox . iweb is long dead. sandvox hasn't seen many updates recently, and i think i'd like to move on to something newer and "better" (in this case, "better" means ios-friendly. e.g., blogo or blogpad pro . also . blogo's support site seems to be a right mess. not a good look. they're working on it.).
the blog isn't the unholy mess. we'll get to the mess below. first, however some background on the overall strategy. i want to move my content. what's involved? there are several things in play: the hosting, the target, and the source. so. essentially. everything.
changing the hosting platform
both of my legacy tools would export and upload the changes to my hosting service directly, avoiding the overheads of having any complex hosting software. the site was static and served simply from the filesystem via apache httpd. publishing was an sftp transfer to the server. nothing more. the "platform" was almost nothing (i could switch to using an amazon s3 bucket and a dns entry and it would work nicely).
both of these offline editing tools have a tiny bias toward working with hosting services like wordpress. blogo claims it can also work with medium, and blogger, as well.
this means running wordpress on top of my default sftp/apache configuration. i use a2 hosting, so this is really easy to do.
so. the hosting is more-or-less settled. i'll do very little (dealing with breaking links is a separate hand-wringing exercise).
in order to move from iweb and sandvox to another tool, and start using wordpress, i have two strategies for converting the content.
- ignore my legacy content. leave it where it is, more-or-less uneditable. the tool(s) are gone, all that's left is the static html output from the tool.
- gather the legacy content and migrate it to wordpress and then pick an offline tool that works with wordpress.
i've already done strategy #1 when i converted from iweb to sandvox. i left the old iweb stuff out there and moved to a new url path with new content. while a clever menu structure can make it look like it's all one multi-year blog, the pages themselves are vastly different in the way they look. there's no comprehensive search. and, of course, i can't easily maintain the old iweb stuff.
having one #1, i'm now sure that's a bad idea.
an advantage of moving to wordpress is the ability to have all of the content in one, uniform database. wordpress has export functionality, so the next tool is a distinct possibility.
getting to wordpress
what we're looking at is a fairly complex data structure. while i'd like to look at this from a vast and reserved distance (i.e., in the abstract) i have a very concrete problem. so, we're forced to consider this from the wordpress pov.
we have a wordpress "site" with a long series of posts and some pages.
the essence here is that the content can — to an extent — be converted to markdown. the titles and dates are easy to preserve. the body? not so much.
we can, as an alternative to markdown, use some kind of skinny html that wordpress supports. i think wp can handle a structure free of class names and using a most of the available html tags.
most of the blog content is relatively flat. the block structure is generally limited to images, block quotes, paragraphs, and ordered and unordered lists. the inline tags in use seem to be a, img, strong, em, and a few span tags for font changes.
the complexity, then, is building a useful content model from the source. there are a few asts for markdown. commonmark.py might have a useful ast. it's not complex, so it may be simpler to define my own.
it's hard to understand the inline blocks in mistletoe. the python-markdown project uses elementtree objects to build the ast. i'm not a fan of this because i'm not parsing markdown.
starting from, well, it's complicated
there are — as noted above — two sources:
the sandvox desktop "database" structure is opaque. the media is easy to find. the content is some kind of binary-encoded data with headers that tell me a little about the xcode environment, but nothing else.
to read this, i have to scrape the html using beautiful soup. it involves processing like this:
content = soup.html.body.find("div", id="main-content") article = content.find(class_="article-content").find(class_="richtextelement").div
find a nested <div> with a target id. inside that <div> is where the article can be found.
this seems to work out pretty well. almost everything i want to preserve can be — sort of — mushed into markdown.
there's a lot of code like this
main_layer = child_root.find('ns0:site-page/ns0:drawables/ns0:main-layer', ns)
this example digs into site pages, nested drawables, and main layers of content. eventually, we wind up looking at <p>, <span>, <attachment-ref>, and <link> tags in the xml to build the relevant content.
the nuance is style. they're not part of the inline markup. they're stored separately, and included by reference. each of the four tags that seem to be in use have a style attribute that references styles defined within the posting. once these references are resolved, i think mardown can be generated.
the unholy mess
the hateful part of this is the disconnect between html (and xml) and markdown. the source data permits indefinite nesting of tags. semantically meaningless <p><p>words</p></p> are legal. the "flattening" from html/xml to markdown is worrisome: what if i trash an entry by missing something important?
ideally, it's this:
pragmatically, html/xml can be more complex. this diagram assumes we won't have paragraphs inside list items. html permits it. it's redundant in markdown.
worse, of course, are the inline tags. html has a kabillion of them. the software i've been using seems to limit me to <img>, <strong>, <em>, and <a>. html/xml allows nesting. markdown doesn't.
ideally, i can reframe the inline tags to create a flat sequence of styled-text objects within any of the tags.
right now. headaches.
working on the code. it's not a general solution to anyone else's problem. but. i'm hoping — as i beat the problem into submission — to find a way to make some useful tutorial materials on mapping between complex, and different, data structures.
Published at DZone with permission of Steven Lott, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.