DTDAnalyzer: A tool for analyzing and manipulating DTDs
CC Attribution 3.0 Unported:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal purpose as long as the work is attributed to the author in the manner specified by the author or licensor.
Hess, Demian
Maloney, Chris
Hamelers, Audrey
This paper describes an open-source Java/XSLT application that allows users to analyze and manipulate XML DTDs. The application can be used to generate reference documentation, create reports comparing two DTDs, convert DTDs into Schematron, and to automatically scaffold conversion scripts.The DtdAnalyzer tool has been used at the National Center for Biotechnology Information (NCBI), a part of the National Library of Medicine, for a number of years, to help maintain the suite of NLM DTDs, and to develop new conversion applications. NCBI has recently decided to release it as a self-contained application and to move its development onto GitHub.The heart of the tool is a Java application which converts a DTD into an XML representation, including all the element, attribute, and entity declarations contained inside the DTD. Additionally, DTDs can be annotated with specially-formatted comments which are recognized by this converter, and these annotations are delivered in the XML output.The resulting XML can be transformed to create many useful outputs, and a basic set of those transformation stylesheets, as described above, are included with this tool.
 Hello. As I was just introduced, my name is Damien Hess. I'm very happy to make this presentation on behalf of my co-presenters and authors, Chris Maloney, Audrey Hemlers, who are both at NLM. And as you heard, I'm Damien Hess at Avalon Consulting, and I am going to be talking about the DTD analyzer, which is a tool. In fact, I'm going to keep referring to it as the tool because saying DTD analyzer gets a little difficult. The way the DTD analyzer works or what it does, it will take any DTD and it will convert it to an XML representation. You can ask what good is that, but I'll get to it. It is an open source project, and we've got the link to where it's hosted on GitHub on the screen, and we encourage everyone visit the GitHub site, download the project, participate, and let us know what you think, and we can make it better. And it is written in Java, so it should be able to run on any operating system. And we've got the command to invoke the basic function of the tool on the screen. You simply say DTD analyzer, you give it the location of a DTD, and you specify a name for this output file, which contains the XML representation of the DTD. Now, what can you do with this representation? We have determined that you can do a lot with it, and we have a couple of use cases where we have found it very useful. First of all, you can analyze your DTD structure and content with the DTD analyzer. As you saw yesterday in the sneak peek, you can also create documentation with the DTD analyzer. And finally, but definitely not least, it's very easy with the output from the analyzer to create scripts that can either manipulate the DTD itself or that can change XML files that conform to your DTD. So we're really talking automated conversion scripts being driven with this tool. I've got examples of all three of these use cases that I am going to walk through during this presentation. And let us start with an analysis use case. This is a pretty common need. Let's say you've got two versions of a DTD, and you want to compare them. Let's say it's the NLM DTD, the publishing version number three, and you've got the brand new NISOJATS DTD, and you're wondering, how are these things different? What's changed? You know, what elements have changed? What elements have been moved? Which elements have been added? You can do that with the DTD analyzer. You can run a comparison report. And we've got the code for this report as part of the project. And actually, this is a static shot of the report. I remember the commands here. Ah, good. We actually have a live version of the comparison report. So as you can see, the output of the comparison is in HTML. So you can view it in your web page. Oh, good. It's big enough to actually see. At the very top of the report, we list how many elements have changed. You can see right there in the summary, 204 elements have changed, going from NLM to NISO. No elements have been removed, but 11 elements have in fact been added. In fact, if you were to jump down, you could see the listing of what's been added. So you have things like AF alternatives, and you have its content model and its attributes. If I go back up to the top, you can scroll through and see a listing of all the elements that have changed. And so you can see, for example, the agree elements, the attributes have changed. The old attributes from NLM are listed on the left. And all of the new attributes, or rather, all of the attributes that are now in NISO are listed on the right. So how do we do this comparison? It's actually very straightforward. Since we've got an XML representation of both of the DTDs, it's very easy to write an XSL that simply steps through both of the XML documents and says, okay, what elements are in this DTD, but not in that DTD and vice versa, and, okay, for every element that's in both DTDs, let's compare their attributes, are those the same, and let's compare the content models. And whatever finds a difference, we can output it in the report. Now, this comparison, I will be the first to admit, is not the most sophisticated in the world. So, for example, if you look at the abstract element, it's listed as having a difference, and we can see the content model of the NLM and the NISO. And you can see that, yeah, the content model technically is different. Or maybe you can't, it's pretty small. What you've got are some extra parentheses. Now, if you speak DTD, you know, actually, that's not significant. They're actually the same content model, but the XSL is simply doing a string comparison, and the strings are different. So it could be more sophisticated. But even though it's only doing this very simple comparison, I've used this tool for a long time. Probably for about five years, I have found it really useful in any kind of conversion projects. It helps me pinpoint the elements that I really need to look at and as a human being do some analysis on. Let's move on. Oops, wrong one. What does this XML representation look like, this thing that's driving these comparisons? This is a high-level view of it. For every DTD, we create this document. The root element is declarations. And then we've got information on all the elements inside the DTD, all of the attributes inside the DTD, all of the parameter and the general entities in the DTD. And we can actually open that up because I've got an example here. This is the output from running the tool on the journal publishing DTD. If I expand the elements section, we can see a listing of every single element in the DTD is represented here in XML. So every element gets an element named element. It's pretty clear if repetitive. You can see the element name. We give information on where the element appears inside the DTD. So for example, you can see that string date is the 54th element in the DTD. We give you the location of the element declaration in the DTD, both in terms of the file name, the public ID for that file, and the line number of the declaration. And most importantly, we capture the content model of the element. And we do that in a couple of different ways. We've got a string form that simply shows the declaration as it appears inside the DTD. But we also parse that string apart and we can give you a structured content model. And this is new. Chris Maloney, excellent work, just actually put this into the DTD analyzer. And you get things like a listing of all the child elements, whether or not it's a sequence, what the cardinality is of all the elements, if there are grouping, there's choices. So that gives you a really rich look at what the content model actually is. And you know how I said before in the comparison, it's not that sophisticated. Well, with this kind of a structure, we could probably do a very sophisticated comparison of how an element has changed from one version of a DTD to another. Just haven't had a chance to try applying that now to the comparison report. So that's definitely on the list of things to try and improve. Oh, I should actually just jump. I don't want to get too in the weeds on how the DTD is modeled. I'll just jump down and just quickly show you how attributes are captured. So every unique attribute name gets captured. And then we show where that attribute is used, which elements, and then exactly the declaration of that attribute within the context of that element. So you can get kind of lost in all this data. So I'll just close it up. Great. Because you're representing your DTD in XML, you can now do all the good stuff that you are used to doing with XML documents. You can apply all the tools to your XML to analyze that DTD now. You can use XPath. So if you want to know how many elements are in the DTD, you just say, count all the elements. If you want to know, this is Audrey's example, how many attributes have multiple declarations, you can write an X query. So what this is doing is, you know how you can have like an alt attribute and it can appear on lots of different elements. And in general, you kind of want the same declaration to be applied for the alt attribute to every element. So it should be required. It should be like an enumerated list. You don't want to make a mistake in your DTD. And actually on some elements make it optional and like just see data and on other elements it's required and it's enumerated. You don't want that. But it's easy to make a typo when you're creating your DTD. Hard to find those problems. But now because everything is in XML, you could write an X query statement like this which actually just loops over all of the attribute declarations and checks them. So it helps you maintain your DTD. Structured comments. So the DTD analyzer, the tool is obviously capturing structural information about your DTD. But it can capture more information than just that. Specifically when the tool runs on the DTD, it looks at every single comment that you've entered into the DTD files. And if you insert special delimiters into those comments, if you structure your comments, the analyzer can read it and extract that information and create what you see on the right. So on the left you create one of these structured comments. You say to till this, the name of the element, and then the text of your comment. When the analyzer sees that comment, it realizes, oh, this is an annotation for the split element. And it will grab that information and create what you see on the right which is an annotations tag with an annotation element inside of it. Now you notice we say annotations with a single annotation. So that implies that yes, you can have more than one annotation for an element because it would be kind of boring if you only had one annotation. You can actually structure your comment to have sections. You can split it up to say I've got a model section, a tag section, and an examples section. And when you create your annotations, we get a model annotation, a tags annotation, and an examples annotation. And as you can see, the analyzer is doing a little bit of magic behind the scenes. Certain section names have significance to the analyzer. So for example, if you put a tags section in your comment, then the analyzer will take all those words and wrap all the words in a tag element. The other bit of magic that's probably even more obvious is it's taking the text and turning it into XHTML. And for that, we are actually using a format called markdown which is kind of like a wiki language. And it will do things like if you put asterisks, it will turn those into bulleted lists. If you indent things a certain way, it turns them into code blocks. So that gives you the opportunity to sort of create even better representational markup inside your annotation. Of course, you may not want XHTML in your annotations. And so you have the option to turn this off. When you generate your XML representation, you just say no markdown. Don't convert anything into XHTML and it won't. So that gives you a lot of control over what your annotations look like. Now, what can you do with this? You actually had a sneak peek of this yesterday. You can take all that structural information and those annotations and you can create really nice documentation directly from your DTD. In fact, it's so good or it's so important we've created a sub tool as part of the project. Well, I didn't do it. That was Chris. You just give the command DTD documenter. You tell it where it should output all of the documentation and then give it the location of your DTD and it will create documentation that looks like this. So this is an example DTD that Chris marked up for us and put into the project and you can download it and take a look at it. We've auto generated the documentation for it and you can see you actually come first of all to like a home page, a landing page about the DTD with like all this text about the DTD. All of that text was inserted into the DTD as an annotation. On the left hand side, we've got all of the elements that are inside the DTD. We have all the attributes inside the DTD. If I click on one of the element names, we go right to the element model. You can see its name, its content model and then we've got this text. For bananas, make a bunch and so do many more. That was an annotation that was attached to that element that was automatically extracted and put into the documentation. I also mentioned that some annotations can be tags. We actually list all of the tags here that appear in the annotations. If you click on one of them, you navigate to which elements are tagged with that word. I think this is really cool because when we were all maintaining our DTDs, we were always writing all these comments into the DTDs, right? But no one ever saw them because only you had access to the DTDs. For all of your end users, you had to create all this additional documentation. You had to create Word documents or PDFs or websites with all that information to explain to people how to use your DTD. Well, that's multiple files to try to have to maintain. You have the option now if you want to, you can embed all of your documentation directly into the DTD and then you just run a single command and you can go from your DTD straight to your documentation because it will extract all of the annotations that you entered. In fact, it is so nifty. We have lots of options and you would have to go to the GitHub site to see what all the options are. But here are some of them. When you generate your documentation, you could say, you know, dash dash roots and then give a list of elements like foobar and baz. And when the documentation gets generated, it will only contain the documentation for foobar and baz plus all of their descendants. You can restrict what's shown in your documentation. You also have the option to say exclude. You could exclude a list of elements or you could say exclude everything that's prefixed with MML. So don't show me any of the math MML elements in my output. I only want to see everything else. You also have the option exclude except. So exclude all the math MML elements except the MML math element. Show that in the documentation. You also have options. You can replace the CSS that's used to style the HTML. You can include a different JavaScript file that you've written so you can control the behavior of the documentation when it's displayed in your browser. And of course, you always have the option, you've got the XML with all the structural information about your DTD plus all the annotations from the DTD. You can write your own process. You could write your own XSL or some other process to generate the exact documentation that you need. Like, for example, maybe you need things output in PDF. You've got the raw XML. You can go ahead and create your own process to do that. Well, as great as documentation is, sometimes it's not quite enough. And here's an example of that. Let's say you've got a DTD like this on the screen that defines a section element that contains other sections and also has a level attribute that lets you set at what level that section is. And in your documentation, because we're using the DTD analyzer, you can say how this element and that attribute should be used. You can explain, you have to nest your sections properly and you can even give an example. You can say, look, section ones contain section twos. Don't put a section one inside a section seven. It's not allowed. The only problem is, is that enough to prevent people from misusing your tags? And anyone who's worked at XML knows, no way. People don't always read the documentation. And even if they have the documentation, they may not understand it. What you'd really like to do is restrict what people can do with your XML. The normal answer to that these days is to do something like create a schema tron file, which is a framework that lets you control the usage of your XML. And so in schema tron, you can write a rule for every section element. And in that rule, you can say, you know, restrict it so that every section's parent's level has to be one less than my level. You know, so that's the rule. And if it's not right, you can insert or output an error message. I'm using a report here. I might have, probably should have used an assert. But anyway, it's all the same thing. You get the idea. Now, the problem with having a schema tron file is, now, again, you've got multiple files. You've got your DTD over here with all the documentation in it. And now you've got all your schema tron files, you know, over here, which are going to enforce the usage. Wouldn't it be nice if you could just insert your schema tron rules directly into the DTD? Because you can. If you want to, you can insert a schema tron section into your comments and then insert the specific test that you want to use to enforce the usage. Okay. Then you say, what do I do? How do I still need a schema tron file? No fears. We've got, or I should say Audrey has authored, an XSL that will go in to the DTD, extract all of the schema tron annotations and create a schema tron file that you can then apply to your normal validation processes. So, in fact, we've got a single command that can go ahead and execute this. You simply say, DTD analyzer, give it the location of your DTD, specify the DTD schema tron XSL and the name of the output file, schema tron SCH. You can then go directly in one command from your DTD to the schema tron file that's going to enforce your usage. I like this a lot because I'm kind of a programmer and a bit of a geek. So, I like the idea that you can go directly from a DTD to human readable documentation, human readable output, or you can go directly from your DTD to machine readable output. In this case, it's a schema tron, but that begs the question, why can't it be something else? Why can't we go directly from the DTD to something like an XSLT? Specifically, can we go from the DTD to a conversion script written in XSL that will then convert content that conforms to my DTD? Can we do automated conversions? And the answer is yes, you can. All you have to do is create what's shown in red, a magic scaffold XSL that will produce another XSL. Now, that tends to give people a headache, an XSL that produces another XSL, but it's perfectly possible to do, and in fact, we've written it. As part of this DTD analyzer project, we have a scaffold XSL, and it will generate a conversion script based on your DTD. But what is that conversion script? Well, okay, now I have to own up to the fact, it doesn't do a lot, and it's not supposed to. What it's supposed to do is serve as a basis for you to continue development on that script. It's a shortcut. It helps you along. Specifically, what scaffold XSL does is it reads through the DTD, and for every element in the DTD, it will output a conversion template for that element. And I grabbed one of the elements to show you. Pretty small. This is for the article element inside, looks like the journal publishing DTD. And this is a good example because it is exactly what every other template looks like. All the templates look exactly like this. It gives you, in the header comments, it shows you the name of the element that's being transformed. It also shows you the content model for that element because of course, we've got access to all the information in the DTD. So that is very handy because when I'm writing conversion scripts, I always forget, like, oh, yeah, what attributes are in this element? What, which are required? Which are optional? You know, I just always have to stop and go and look it up. Now I don't have to. I can just keep focusing on my script and there all the information is. In addition, the body of the template, all this does is it just copies the element out unchanged. Now of course, I don't actually want that. I want to change that element to something. So now I, as a programmer, can go in though and then just, you know, tweak this template to do what I want. Or think about this way. What if I went through the DTD and I annotated it? And I wrote in an annotation, this element should become this other element. I could then go and adjust scaffold.xsl so that rather than output the element unchanged, it could output the element that I told it to. Now what if, in fact, it wasn't me doing the annotation, but maybe it's the analyst. Maybe the DTD architect should go in as the analyst and do all the annotation. And then the programmer can focus on writing a script that follows the rules spelled out in the annotation. So then you could get a nice separation of responsibilities. So that's the advantage of scaffolding. Scaffolding is the automated generation of code. And in this case, huge advantage, reduces typing. I don't have to go in and type a rule for every single element, which I have to do anyway, because the code is generated for me. No typos. I won't overlook anything. It's all done automatically. It can enforce coding conventions. They all look exactly the same. Whatever I want my coding conventions to be, my indenting, my, how my header comments should look, it's done for me. We get uniformity of code in case you give the project to other people to work on. And of course, with auto generation of code, it can be driven by annotations. Again, helps you further along to automate the process and you can start dividing up the responsibility of some people working on annotations and analysis and other people working on implementation. Now, all of that was kind of theoretical. Let me give you an actual example of a real problem that I really did solve using the analyzer, or at least a version of the analyzer that I had, and a version of scaffold.xsl. It's kind of a weird example, but it's real at least. So I used to work at a company and we had a big conversion project. Specifically, we had about 30 years worth of book content and these were big, fat directories full of people's names and phone numbers and addresses and emails. And we had about 30 years of these big, fat directory books that we wanted to convert to XML. So we were boxing them up and shipping them off to a conversion house and they were scanning them and turning them into XML. Now, with that kind of a structure, the data to tag ratio is not great. There's little bits of data and lots of tags. And we realize we're paying by the kilobyte of output. And we realize, you know, if we just shorten up our tag names, like make them all two-letter tags, I'm serious, we could save a lot of money. I mean, I think we saved at least 20% of our budget in conversion just by reducing the tag names. So what we needed, though, we needed a script to automatically shorten up all of our tag names, to minify our tag names. And even more important because those were hard to read, we needed a script that would automatically expand the tag names back to their normal state. That was really easy to do with the analyzer. I took the scaffold XSL, I added one function. All the function did was just calculate a short name. And then I did the opposite. I just wrote another, just made another copy of it and matched on the minimize name and output the regular name. Two scripts. It took me 30 minutes to write them both. In fact, I know that's true because I just rewrote them the other night for this presentation 30 minutes. I could run any DTD through it and I could go from a minified form of the XML to a restored form of the XML automatically. And I could go from the expanded to the minified automatically, guaranteed no data loss. It's just automatic. That's pretty nice. And even nicer, this is really going crazy, we also auto-generated a minified DTD. So you could take your minified, weird two element tag names and just validate it. And I auto-generated this DTD in exactly the same way. I just wrote a special XSL at output the minified form of the DTD. Now this can seem kind of, by the way, the two letter tag names base 26. Anyway, that's all I'm going to say about that. This minified version of the DTD and the scripts can seem kind of esoteric. Okay, that worked in one case. But then I suddenly realized yesterday, actually this could be generalized a bit more. It's exactly the same thing. Like what if you want to have multilingual tags? So rather than outputting all your tag names, this is the authoring DTD I think, rather than outputting all your tag names in English, it's the same thing. You just annotate your DTD to give an alternate tag name and you can automatically output all your tags in French or Chinese or Japanese, whatever people want. And then you can even auto-generate the DTD to validate it. And then you can also just change it back to English whenever you want to. I don't know. It seems kind of cool to me. We'll see. Maybe we'll work on this as a project. Future possibilities. Well, that's one. You could do multilingual tagging. Other things we could work on. Chris has got a lot of ideas about this. Maybe I can talk about this. We could probably do tighter integration with the JATS documentation that's available. Maybe one way of doing that. Maybe we could get annotations inserted into the actual official released version of the DTD. That's one way of doing it. But then, of course, the problem with that is if you ever make changes to the documentation, then you've already distributed it to all these other people and they don't get the changes. So maybe another way of doing it is we could change the DTD documenter so that when it generates documentation for you, it goes out to a public website and pulls the annotations down. That's a possibility. Almost done. Obviously, I mentioned we could use the structured content model to create a better DTD compare. That's an option. And definitely what I was talking about with multilingual scripting or automated conversion, find ways to leverage annotations, good patterns that we could suggest to other people to automatically scaffold and script out our conversion projects. And, of course, we want to promote community use. And toward that end, here are the links. Go to the GitHub project page, join the mailing list, and try it out. And if you find bugs, someone, you can report them and someone will take a look at those issues. So thank you very much. We think we'll open up the questions. Bruce Rosenblum from Enera. This question is almost directed more to Jeff and to Laura. But in watching the presentation, it strikes me that there are different profiles for Jats, one of which is sort of the public tag library that we all work with online. But another is the profile of Jats is required for PubMed Central. And would it be possible using their tools to have for those people who are interested in submitting to PubMed Central, an annotated version of the tag libraries that have the additional information you need to know about what are the PubMed Central rules, particularly those enforced by the style checker? So that because one of the problems I run into is I often hear from customers, gee, I'm getting this error from a style checker I haven't seen before what happened and I end up writing to you guys and I go, oh, you've added a new rule to style checker, but there's no documentation on that rule. So it would be great help if that could be integrated in possibly using these tools. We will not integrate PMC rules with the Jats documentation as generically. We will not. Clarification. I'm not looking for generic. I'm looking for a parallel set of documentation that's documentation of the PMC profile of Jats. Which is the tag tagging guidelines. Can't you integrate it on an element by element basis using these tools? It would make the life of developers who are preparing content for deposit to PMC much simpler. It would be a significant time investment and I don't know that we have the resources at this time. It's interesting. Oh, it's absolutely interesting. But it would be a significant time investment because we have built the tagging guidelines and if we did what Bruce is suggesting, we would have to rebuild the tagging guidelines in a completely different new way. It's absolutely something we could do with this tool, but can we do it now? No, we don't have the time or the resources at this moment. The fact that it's interesting and something you could do is great. We'll pray for a future improvement there. Yeah, it's definitely interesting. And I would like to say it makes a really good case for what he was talking about at the end about bringing in the annotations from externally as opposed to putting them in the DTD. You can't put PMC in the DTD, but they could certainly come in externally. That's right. That was my impression. It could be layered on top of the core JASDTDs potentially. By the way, I should have started out by saying, yes, the tools are really, really cool. Here's my use case that I want to see. Yeah, fortunately Audrey is on our team. She's got nothing but time. Wendell Pease, Pease Consulting. So have you guys done a heads up comparison to other tools in the industry that do similar things so you can give us a feature profile? I'm thinking of NECO DTD, which I've used for years to do this. So that's the obvious candidate. There are some older ones as well. It would be really nice if we could see, okay, this is what this tool does, and this is the XMO profile, get out of that, the features of it versus this one over here so I could make a fast decision on that. Because of course, the first thing that happens is you start investing development cycles and the cool stuff you build on top. So you want to know early on where the feature set is. There is some information about that in our paper. We compare it to a couple of different DTD tools. We certainly haven't done a universal analysis of other tools and looking for gaps and differences between those. Yeah, we definitely could do more. We haven't done an official analysis really closely looking at all the different tool sets. I've certainly looked at TRANG, and I'm familiar with the way that that converts DTDs into XML. And I always found that too much information for what I wanted, but as a tool that actually do the analysis for you or that do comparisons, I haven't had a chance to look at any other. Right. Well, the particular functionality that you need or something like this, actually TRANG doesn't give you. Because TRANG does a straight conversion of all the parameter entities into patterns and so forth. And what you need is the breakout. And you're giving us the breakout in some form, which is obviously the right thing to do. But even if you didn't have a feature set, a schema to tell you what is in your model to compare it to the, you know, what comes out of. I mean, I think the obvious candidate here is the NECO DTD tool from Apache, which does a similar thing. And it'd be great to see what that is. So, brought up the Wiki page on GitHub of similar tools, and it's a Wiki, so go ahead and add any application that you want on there. Yeah, NECO DTD is there. So you're inviting me to do the work that I asked you to do. Yes, that's why it's on GitHub as an open source project is we're looking for other people to participate. Well, if you have any information to share. I asked from Nature, just a quick question about the schema tool, DTD schema tool. You talked about it. Can this be used to generate tagging card lines? Yes. So if you provide the DTD and the schema tool rules, can this be, I think, to get a generate tagging card lines documentation? Yes. Yes, I think that would be a good use for it. That was how it was intended to be used. Could you tell us how, how, because you haven't described it in your presentation? Well, it does require you to be able to generate your own schema rule that will enforce your tagging guidelines. Really, it's a way to combine schema tron and your annotations and multiple things that you need when you're maintaining a DTD into one easy to update file. Yeah. Okay. Okay. Thanks. Thank you very much. Really, really cool stuff. But I would really urge you to explore very hard the possibility of bringing those things in from a separate file and marrying them to the DTD. Yes. Because we're all using the same Jets DTD here, and I bet we're all using different schema trons. Yeah. And actually, what you can do is the annotations, at the beginning of the annotation of the comment, you specify what element it's attached to or which attribute it attaches to. So you can actually put all those comments in a separate file. That's my suggestion. Yeah. Layering. Layering is wonderful. But you could create one top-level DTD that contains those and pulls in the other DTD as an entity, as a general entity. You could. Yes. That would work. But I'm suggesting you really might want to look into layering here very carefully. I thought that's what I just described. Okay. Thank you all very much.
 Hello. As I was just introduced, my name is Damien Hess. I'm very happy to make this presentation  on behalf of my co-presenters and authors, Chris Maloney, Audrey Hemlers, who are both  at NLM. And as you heard, I'm Damien Hess at Avalon Consulting, and I am going to be  talking about the DTD analyzer, which is a tool. In fact, I'm going to keep referring  to it as the tool because saying DTD analyzer gets a little difficult. The way the DTD analyzer  works or what it does, it will take any DTD and it will convert it to an XML representation.  You can ask what good is that, but I'll get to it. It is an open source project, and we've  got the link to where it's hosted on GitHub on the screen, and we encourage everyone visit  the GitHub site, download the project, participate, and let us know what you think, and we can  make it better. And it is written in Java, so it should be able to run on any operating  system. And we've got the command to invoke the basic function of the tool on the screen.  You simply say DTD analyzer, you give it the location of a DTD, and you specify a name  for this output file, which contains the XML representation of the DTD. Now, what can you  do with this representation? We have determined that you can do a lot with it, and we have  a couple of use cases where we have found it very useful. First of all, you can analyze  your DTD structure and content with the DTD analyzer. As you saw yesterday in the sneak  peek, you can also create documentation with the DTD analyzer. And finally, but definitely  not least, it's very easy with the output from the analyzer to create scripts that can  either manipulate the DTD itself or that can change XML files that conform to your DTD.  So we're really talking automated conversion scripts being driven with this tool. I've  got examples of all three of these use cases that I am going to walk through during this  presentation. And let us start with an analysis use case. This is a pretty common need. Let's  say you've got two versions of a DTD, and you want to compare them. Let's say it's the  NLM DTD, the publishing version number three, and you've got the brand new NISOJATS DTD,  and you're wondering, how are these things different? What's changed? You know, what  elements have changed? What elements have been moved? Which elements have been added?  You can do that with the DTD analyzer. You can run a comparison report. And we've got  the code for this report as part of the project. And actually, this is a static shot of the  report. I remember the commands here. Ah, good. We actually have a live version of the comparison  report. So as you can see, the output of the comparison is in HTML. So you can view it  in your web page. Oh, good. It's big enough to actually see. At the very top of the report,  we list how many elements have changed. You can see right there in the summary, 204 elements  have changed, going from NLM to NISO. No elements have been removed, but 11 elements have in  fact been added. In fact, if you were to jump down, you could see the listing of what's  been added. So you have things like AF alternatives, and you have its content model and its attributes.  If I go back up to the top, you can scroll through and see a listing of all the elements  that have changed. And so you can see, for example, the agree elements, the attributes  have changed. The old attributes from NLM are listed on the left. And all of the new  attributes, or rather, all of the attributes that are now in NISO are listed on the right.  So how do we do this comparison? It's actually very straightforward. Since we've got an  XML representation of both of the DTDs, it's very easy to write an XSL that simply steps  through both of the XML documents and says, okay, what elements are in this DTD, but not  in that DTD and vice versa, and, okay, for every element that's in both DTDs, let's compare  their attributes, are those the same, and let's compare the content models. And whatever  finds a difference, we can output it in the report. Now, this comparison, I will be the  first to admit, is not the most sophisticated in the world. So, for example, if you look  at the abstract element, it's listed as having a difference, and we can see the content model  of the NLM and the NISO. And you can see that, yeah, the content model technically is different.  Or maybe you can't, it's pretty small. What you've got are some extra parentheses. Now,  if you speak DTD, you know, actually, that's not significant. They're actually the same  content model, but the XSL is simply doing a string comparison, and the strings are different.  So it could be more sophisticated. But even though it's only doing this very simple comparison,  I've used this tool for a long time. Probably for about five years, I have found it really  useful in any kind of conversion projects. It helps me pinpoint the elements that I really  need to look at and as a human being do some analysis on. Let's move on. Oops, wrong one.  What does this XML representation look like, this thing that's driving these comparisons?  This is a high-level view of it. For every DTD, we create this document. The root element  is declarations. And then we've got information on all the elements inside the DTD, all of  the attributes inside the DTD, all of the parameter and the general entities in the DTD.  And we can actually open that up because I've got an example here. This is the output from  running the tool on the journal publishing DTD. If I expand the elements section, we  can see a listing of every single element in the DTD is represented here in XML. So  every element gets an element named element. It's pretty clear if repetitive. You can see  the element name. We give information on where the element appears inside the DTD. So for  example, you can see that string date is the 54th element in the DTD. We give you the location  of the element declaration in the DTD, both in terms of the file name, the public ID for  that file, and the line number of the declaration. And most importantly, we capture the content  model of the element. And we do that in a couple of different ways. We've got a string  form that simply shows the declaration as it appears inside the DTD. But we also parse  that string apart and we can give you a structured content model. And this is new. Chris Maloney,  excellent work, just actually put this into the DTD analyzer. And you get things like  a listing of all the child elements, whether or not it's a sequence, what the cardinality  is of all the elements, if there are grouping, there's choices. So that gives you a really  rich look at what the content model actually is. And you know how I said before in the  comparison, it's not that sophisticated. Well, with this kind of a structure, we could probably  do a very sophisticated comparison of how an element has changed from one version of  a DTD to another. Just haven't had a chance to try applying that now to the comparison  report. So that's definitely on the list of things to try and improve. Oh, I should actually  just jump. I don't want to get too in the weeds on how the DTD is modeled. I'll just  jump down and just quickly show you how attributes are captured. So every unique attribute name  gets captured. And then we show where that attribute is used, which elements, and then  exactly the declaration of that attribute within the context of that element. So you  can get kind of lost in all this data. So I'll just close it up. Great. Because you're  representing your DTD in XML, you can now do all the good stuff that you are used to  doing with XML documents. You can apply all the tools to your XML to analyze that DTD  now. You can use XPath. So if you want to know how many elements are in the DTD, you  just say, count all the elements. If you want to know, this is Audrey's example, how many  attributes have multiple declarations, you can write an X query. So what this is doing  is, you know how you can have like an alt attribute and it can appear on lots of different  elements. And in general, you kind of want the same declaration to be applied for the  alt attribute to every element. So it should be required. It should be like an enumerated  list. You don't want to make a mistake in your DTD. And actually on some elements make  it optional and like just see data and on other elements it's required and it's enumerated.  You don't want that. But it's easy to make a typo when you're creating your DTD. Hard  to find those problems. But now because everything is in XML, you could write an X query statement  like this which actually just loops over all of the attribute declarations and checks them.  So it helps you maintain your DTD. Structured comments. So the DTD analyzer, the tool is  obviously capturing structural information about your DTD. But it can capture more information  than just that. Specifically when the tool runs on the DTD, it looks at every single  comment that you've entered into the DTD files. And if you insert special delimiters into  those comments, if you structure your comments, the analyzer can read it and extract that  information and create what you see on the right. So on the left you create one of these  structured comments. You say to till this, the name of the element, and then the text  of your comment. When the analyzer sees that comment, it realizes, oh, this is an annotation  for the split element. And it will grab that information and create what you see on the  right which is an annotations tag with an annotation element inside of it. Now you notice  we say annotations with a single annotation. So that implies that yes, you can have more  than one annotation for an element because it would be kind of boring if you only had  one annotation. You can actually structure your comment to have sections. You can split  it up to say I've got a model section, a tag section, and an examples section. And when  you create your annotations, we get a model annotation, a tags annotation, and an examples  annotation. And as you can see, the analyzer is doing a little bit of magic behind the  scenes. Certain section names have significance to the analyzer. So for example, if you put  a tags section in your comment, then the analyzer will take all those words and wrap all the  words in a tag element. The other bit of magic that's probably even more obvious is it's  taking the text and turning it into XHTML. And for that, we are actually using a format  called markdown which is kind of like a wiki language. And it will do things like if you  put asterisks, it will turn those into bulleted lists. If you indent things a certain way,  it turns them into code blocks. So that gives you the opportunity to sort of create even  better representational markup inside your annotation. Of course, you may not want XHTML  in your annotations. And so you have the option to turn this off. When you generate your XML  representation, you just say no markdown. Don't convert anything into XHTML and it won't.  So that gives you a lot of control over what your annotations look like. Now, what can  you do with this? You actually had a sneak peek of this yesterday. You can take all that  structural information and those annotations and you can create really nice documentation  directly from your DTD. In fact, it's so good or it's so important we've created a sub tool  as part of the project. Well, I didn't do it. That was Chris. You just give the command  DTD documenter. You tell it where it should output all of the documentation and then give  it the location of your DTD and it will create documentation that looks like this. So this  is an example DTD that Chris marked up for us and put into the project and you can download  it and take a look at it. We've auto generated the documentation for it and you can see you  actually come first of all to like a home page, a landing page about the DTD with like  all this text about the DTD. All of that text was inserted into the DTD as an annotation.  On the left hand side, we've got all of the elements that are inside the DTD. We have  all the attributes inside the DTD. If I click on one of the element names, we go right to  the element model. You can see its name, its content model and then we've got this text.  For bananas, make a bunch and so do many more. That was an annotation that was attached to  that element that was automatically extracted and put into the documentation. I also mentioned  that some annotations can be tags. We actually list all of the tags here that appear in the  annotations. If you click on one of them, you navigate to which elements are tagged  with that word. I think this is really cool because when we were all maintaining our DTDs,  we were always writing all these comments into the DTDs, right? But no one ever saw them  because only you had access to the DTDs. For all of your end users, you had to create all  this additional documentation. You had to create Word documents or PDFs or websites  with all that information to explain to people how to use your DTD. Well, that's multiple  files to try to have to maintain. You have the option now if you want to, you can embed  all of your documentation directly into the DTD and then you just run a single command  and you can go from your DTD straight to your documentation because it will extract all of  the annotations that you entered. In fact, it is so nifty. We have lots of options and  you would have to go to the GitHub site to see what all the options are. But here are  some of them. When you generate your documentation, you could say, you know, dash dash roots  and then give a list of elements like foobar and baz. And when the documentation gets generated,  it will only contain the documentation for foobar and baz plus all of their descendants.  You can restrict what's shown in your documentation. You also have the option to say exclude. You  could exclude a list of elements or you could say exclude everything that's prefixed with  MML. So don't show me any of the math MML elements in my output. I only want to see everything  else. You also have the option exclude except. So exclude all the math MML elements except  the MML math element. Show that in the documentation. You also have options. You can replace the  CSS that's used to style the HTML. You can include a different JavaScript file that you've  written so you can control the behavior of the documentation when it's displayed in your  browser. And of course, you always have the option, you've got the XML with all the structural  information about your DTD plus all the annotations from the DTD. You can write your own process.  You could write your own XSL or some other process to generate the exact documentation  that you need. Like, for example, maybe you need things output in PDF. You've got the  raw XML. You can go ahead and create your own process to do that. Well, as great as  documentation is, sometimes it's not quite enough. And here's an example of that. Let's  say you've got a DTD like this on the screen that defines a section element that contains  other sections and also has a level attribute that lets you set at what level that section  is. And in your documentation, because we're using the DTD analyzer, you can say how this  element and that attribute should be used. You can explain, you have to nest your sections  properly and you can even give an example. You can say, look, section ones contain section  twos. Don't put a section one inside a section seven. It's not allowed. The only problem is,  is that enough to prevent people from misusing your tags? And anyone who's worked at XML  knows, no way. People don't always read the documentation. And even if they have the documentation,  they may not understand it. What you'd really like to do is restrict what people can do  with your XML. The normal answer to that these days is to do something like create a schema  tron file, which is a framework that lets you control the usage of your XML. And so in  schema tron, you can write a rule for every section element. And in that rule, you can  say, you know, restrict it so that every section's parent's level has to be one less  than my level. You know, so that's the rule. And if it's not right, you can insert or output  an error message. I'm using a report here. I might have, probably should have used an  assert. But anyway, it's all the same thing. You get the idea. Now, the problem with having  a schema tron file is, now, again, you've got multiple files. You've got your DTD over  here with all the documentation in it. And now you've got all your schema tron files,  you know, over here, which are going to enforce the usage. Wouldn't it be nice if you could  just insert your schema tron rules directly into the DTD? Because you can. If you want  to, you can insert a schema tron section into your comments and then insert the specific  test that you want to use to enforce the usage. Okay. Then you say, what do I do? How do I  still need a schema tron file? No fears. We've got, or I should say Audrey has authored,  an XSL that will go in to the DTD, extract all of the schema tron annotations and create  a schema tron file that you can then apply to your normal validation processes. So, in  fact, we've got a single command that can go ahead and execute this. You simply say,  DTD analyzer, give it the location of your DTD, specify the DTD schema tron XSL and the  name of the output file, schema tron SCH. You can then go directly in one command from  your DTD to the schema tron file that's going to enforce your usage. I like this a lot because  I'm kind of a programmer and a bit of a geek. So, I like the idea that you can go directly  from a DTD to human readable documentation, human readable output, or you can go directly  from your DTD to machine readable output. In this case, it's a schema tron, but that  begs the question, why can't it be something else? Why can't we go directly from the DTD  to something like an XSLT? Specifically, can we go from the DTD to a conversion script  written in XSL that will then convert content that conforms to my DTD? Can we do automated  conversions? And the answer is yes, you can. All you have to do is create what's shown  in red, a magic scaffold XSL that will produce another XSL. Now, that tends to give people  a headache, an XSL that produces another XSL, but it's perfectly possible to do, and in  fact, we've written it. As part of this DTD analyzer project, we have a scaffold XSL,  and it will generate a conversion script based on your DTD. But what is that conversion  script? Well, okay, now I have to own up to the fact, it doesn't do a lot, and it's not  supposed to. What it's supposed to do is serve as a basis for you to continue development  on that script. It's a shortcut. It helps you along. Specifically, what scaffold XSL  does is it reads through the DTD, and for every element in the DTD, it will output a conversion  template for that element. And I grabbed one of the elements to show you. Pretty small.  This is for the article element inside, looks like the journal publishing DTD. And this  is a good example because it is exactly what every other template looks like. All the templates  look exactly like this. It gives you, in the header comments, it shows you the name of  the element that's being transformed. It also shows you the content model for that element  because of course, we've got access to all the information in the DTD. So that is very  handy because when I'm writing conversion scripts, I always forget, like, oh, yeah,  what attributes are in this element? What, which are required? Which are optional? You  know, I just always have to stop and go and look it up. Now I don't have to. I can just  keep focusing on my script and there all the information is. In addition, the body of the  template, all this does is it just copies the element out unchanged. Now of course,  I don't actually want that. I want to change that element to something. So now I, as a  programmer, can go in though and then just, you know, tweak this template to do what I  want. Or think about this way. What if I went through the DTD and I annotated it? And I  wrote in an annotation, this element should become this other element. I could then go  and adjust scaffold.xsl so that rather than output the element unchanged, it could output  the element that I told it to. Now what if, in fact, it wasn't me doing the annotation,  but maybe it's the analyst. Maybe the DTD architect should go in as the analyst and  do all the annotation. And then the programmer can focus on writing a script that follows  the rules spelled out in the annotation. So then you could get a nice separation of responsibilities.  So that's the advantage of scaffolding. Scaffolding is the automated generation of code. And in  this case, huge advantage, reduces typing. I don't have to go in and type a rule for every  single element, which I have to do anyway, because the code is generated for me. No typos.  I won't overlook anything. It's all done automatically. It can enforce coding conventions. They all  look exactly the same. Whatever I want my coding conventions to be, my indenting, my,  how my header comments should look, it's done for me. We get uniformity of code in case  you give the project to other people to work on. And of course, with auto generation of  code, it can be driven by annotations. Again, helps you further along to automate the process  and you can start dividing up the responsibility of some people working on annotations and  analysis and other people working on implementation. Now, all of that was kind of theoretical.  Let me give you an actual example of a real problem that I really did solve using the analyzer,  or at least a version of the analyzer that I had, and a version of scaffold.xsl. It's  kind of a weird example, but it's real at least. So I used to work at a company and  we had a big conversion project. Specifically, we had about 30 years worth of book content  and these were big, fat directories full of people's names and phone numbers and addresses  and emails. And we had about 30 years of these big, fat directory books that we wanted to  convert to XML. So we were boxing them up and shipping them off to a conversion house  and they were scanning them and turning them into XML. Now, with that kind of a structure,  the data to tag ratio is not great. There's little bits of data and lots of tags. And  we realize we're paying by the kilobyte of output. And we realize, you know, if we just  shorten up our tag names, like make them all two-letter tags, I'm serious, we could save  a lot of money. I mean, I think we saved at least 20% of our budget in conversion just  by reducing the tag names. So what we needed, though, we needed a script to automatically  shorten up all of our tag names, to minify our tag names. And even more important because  those were hard to read, we needed a script that would automatically expand the tag names  back to their normal state. That was really easy to do with the analyzer. I took the scaffold  XSL, I added one function. All the function did was just calculate a short name. And then  I did the opposite. I just wrote another, just made another copy of it and matched on  the minimize name and output the regular name. Two scripts. It took me 30 minutes to write  them both. In fact, I know that's true because I just rewrote them the other night for this  presentation 30 minutes. I could run any DTD through it and I could go from a minified  form of the XML to a restored form of the XML automatically. And I could go from the  expanded to the minified automatically, guaranteed no data loss. It's just automatic. That's  pretty nice. And even nicer, this is really going crazy, we also auto-generated a minified  DTD. So you could take your minified, weird two element tag names and just validate it.  And I auto-generated this DTD in exactly the same way. I just wrote a special XSL at output  the minified form of the DTD. Now this can seem kind of, by the way, the two letter tag  names base 26. Anyway, that's all I'm going to say about that. This minified version of  the DTD and the scripts can seem kind of esoteric. Okay, that worked in one case. But then I suddenly  realized yesterday, actually this could be generalized a bit more. It's exactly the same  thing. Like what if you want to have multilingual tags? So rather than outputting all your tag  names, this is the authoring DTD I think, rather than outputting all your tag names in English,  it's the same thing. You just annotate your DTD to give an alternate tag name and you  can automatically output all your tags in French or Chinese or Japanese, whatever people  want. And then you can even auto-generate the DTD to validate it. And then you can also  just change it back to English whenever you want to. I don't know. It seems kind of cool  to me. We'll see. Maybe we'll work on this as a project. Future possibilities. Well,  that's one. You could do multilingual tagging. Other things we could work on. Chris has got  a lot of ideas about this. Maybe I can talk about this. We could probably do tighter integration  with the JATS documentation that's available. Maybe one way of doing that. Maybe we could  get annotations inserted into the actual official released version of the DTD. That's one way  of doing it. But then, of course, the problem with that is if you ever make changes to the  documentation, then you've already distributed it to all these other people and they don't  get the changes. So maybe another way of doing it is we could change the DTD documenter  so that when it generates documentation for you, it goes out to a public website and pulls  the annotations down. That's a possibility. Almost done. Obviously, I mentioned we could  use the structured content model to create a better DTD compare. That's an option. And  definitely what I was talking about with multilingual scripting or automated conversion, find ways  to leverage annotations, good patterns that we could suggest to other people to automatically  scaffold and script out our conversion projects. And, of course, we want to promote community  use. And toward that end, here are the links. Go to the GitHub project page, join the mailing  list, and try it out. And if you find bugs, someone, you can report them and someone will  take a look at those issues. So thank you very much. We think we'll open up the questions.  Bruce Rosenblum from Enera. This question is almost directed more to Jeff and to Laura.  But in watching the presentation, it strikes me that there are different profiles for Jats,  one of which is sort of the public tag library that we all work with online. But another  is the profile of Jats is required for PubMed Central. And would it be possible using their  tools to have for those people who are interested in submitting to PubMed Central, an annotated  version of the tag libraries that have the additional information you need to know about  what are the PubMed Central rules, particularly those enforced by the style checker? So that  because one of the problems I run into is I often hear from customers, gee, I'm getting  this error from a style checker I haven't seen before what happened and I end up writing  to you guys and I go, oh, you've added a new rule to style checker, but there's no documentation  on that rule. So it would be great help if that could be integrated in possibly using  these tools. We will not integrate PMC rules with the Jats documentation as generically.  We will not. Clarification. I'm not looking for generic. I'm looking for a parallel set  of documentation that's documentation of the PMC profile of Jats. Which is the tag  tagging guidelines. Can't you integrate it on an element by element basis using these  tools? It would make the life of developers who are preparing content for deposit to PMC  much simpler. It would be a significant time investment and I don't know that we have  the resources at this time. It's interesting. Oh, it's absolutely interesting. But it would  be a significant time investment because we have built the tagging guidelines and if  we did what Bruce is suggesting, we would have to rebuild the tagging guidelines in  a completely different new way. It's absolutely something we could do with this tool, but  can we do it now? No, we don't have the time or the resources at this moment. The fact  that it's interesting and something you could do is great. We'll pray for a future improvement  there. Yeah, it's definitely interesting. And I would like to say it makes a really  good case for what he was talking about at the end about bringing in the annotations  from externally as opposed to putting them in the DTD. You can't put PMC in the DTD,  but they could certainly come in externally. That's right. That was my impression. It could  be layered on top of the core JASDTDs potentially. By the way, I should have started out by saying,  yes, the tools are really, really cool. Here's my use case that I want to see. Yeah, fortunately  Audrey is on our team. She's got nothing but time. Wendell Pease, Pease Consulting. So  have you guys done a heads up comparison to other tools in the industry that do similar  things so you can give us a feature profile? I'm thinking of NECO DTD, which I've used  for years to do this. So that's the obvious candidate. There are some older ones as well.  It would be really nice if we could see, okay, this is what this tool does, and this is the  XMO profile, get out of that, the features of it versus this one over here so I could  make a fast decision on that. Because of course, the first thing that happens is you start  investing development cycles and the cool stuff you build on top. So you want to know  early on where the feature set is. There is some information about that in our paper.  We compare it to a couple of different DTD tools. We certainly haven't done a universal  analysis of other tools and looking for gaps and differences between those. Yeah, we definitely  could do more. We haven't done an official analysis really closely looking at all the  different tool sets. I've certainly looked at TRANG, and I'm familiar with the way that  that converts DTDs into XML. And I always found that too much information for what I  wanted, but as a tool that actually do the analysis for you or that do comparisons, I  haven't had a chance to look at any other. Right. Well, the particular functionality  that you need or something like this, actually TRANG doesn't give you. Because TRANG does  a straight conversion of all the parameter entities into patterns and so forth. And what  you need is the breakout. And you're giving us the breakout in some form, which is obviously  the right thing to do. But even if you didn't have a feature set, a schema to tell you what  is in your model to compare it to the, you know, what comes out of. I mean, I think the  obvious candidate here is the NECO DTD tool from Apache, which does a similar thing. And  it'd be great to see what that is. So, brought up the Wiki page on GitHub of similar tools,  and it's a Wiki, so go ahead and add any application that you want on there. Yeah, NECO DTD is there.  So you're inviting me to do the work that I asked you to do.  Yes, that's why it's on GitHub as an open source project is we're looking for other  people to participate. Well, if you have any information to share.  I asked from Nature, just a quick question about the schema tool, DTD schema tool. You  talked about it. Can this be used to generate tagging card lines?  Yes. So if you provide the DTD and the schema tool rules, can this be, I think, to get a  generate tagging card lines documentation? Yes.  Yes, I think that would be a good use for it.  That was how it was intended to be used.  Could you tell us how, how, because you haven't described it in your presentation?  Well, it does require you to be able to generate your own schema rule that will enforce your  tagging guidelines. Really, it's a way to combine schema tron and your annotations and  multiple things that you need when you're maintaining a DTD into one easy to update file.  Yeah. Okay. Okay.  Thanks. Thank you very much. Really, really cool stuff.  But I would really urge you to explore very hard the possibility of bringing those things  in from a separate file and marrying them to the DTD.  Yes.  Because we're all using the same Jets DTD here, and I bet we're all using different  schema trons.  Yeah. And actually, what you can do is the annotations, at the beginning of the annotation  of the comment, you specify what element it's attached to or which attribute it attaches  to. So you can actually put all those comments in a separate file.  That's my suggestion. Yeah. Layering. Layering is wonderful.  But you could create one top-level DTD that contains those and pulls in the other DTD  as an entity, as a general entity.  You could. Yes. That would work. But I'm suggesting you really might want to look into layering  here very carefully.  I thought that's what I just described.  Okay. Thank you all very much.
DtdAnalyzer__A_tool_for_analyzing_and_manipulating_DTDs__0_2351.png DtdAnalyzer__A_tool_for_analyzing_and_manipulating_DTDs__2352_3011.png DtdAnalyzer__A_tool_for_analyzing_and_manipulating_DTDs__3012_3131.png DtdAnalyzer__A_tool_for_analyzing_and_manipulating_DTDs__3132_3383.png DtdAnalyzer__A_tool_for_analyzing_and_manipulating_DTDs__3384_5231.png DtdAnalyzer__A_tool_for_analyzing_and_manipulating_DTDs__5232_9203.png DtdAnalyzer__A_tool_for_analyzing_and_manipulating_DTDs__9204_12755.png DtdAnalyzer__A_tool_for_analyzing_and_manipulating_DTDs__12756_17027.png DtdAnalyzer__A_tool_for_analyzing_and_manipulating_DTDs__17028_17423.png DtdAnalyzer__A_tool_for_analyzing_and_manipulating_DTDs__17424_22271.png DtdAnalyzer__A_tool_for_analyzing_and_manipulating_DTDs__22272_23939.png DtdAnalyzer__A_tool_for_analyzing_and_manipulating_DTDs__23940_23999.png DtdAnalyzer__A_tool_for_analyzing_and_manipulating_DTDs__24000_24779.png DtdAnalyzer__A_tool_for_analyzing_and_manipulating_DTDs__24780_27383.png DtdAnalyzer__A_tool_for_analyzing_and_manipulating_DTDs__27384_28127.png DtdAnalyzer__A_tool_for_analyzing_and_manipulating_DTDs__28128_30587.png DtdAnalyzer__A_tool_for_analyzing_and_manipulating_DTDs__30588_40667.png DtdAnalyzer__A_tool_for_analyzing_and_manipulating_DTDs__40668_40883.png DtdAnalyzer__A_tool_for_analyzing_and_manipulating_DTDs__40884_42479.png DtdAnalyzer__A_tool_for_analyzing_and_manipulating_DTDs__42480_45515.png DtdAnalyzer__A_tool_for_analyzing_and_manipulating_DTDs__45516_45683.png DtdAnalyzer__A_tool_for_analyzing_and_manipulating_DTDs__45684_48275.png DtdAnalyzer__A_tool_for_analyzing_and_manipulating_DTDs__48276_49115.png DtdAnalyzer__A_tool_for_analyzing_and_manipulating_DTDs__49116_51299.png DtdAnalyzer__A_tool_for_analyzing_and_manipulating_DTDs__51300_51647.png DtdAnalyzer__A_tool_for_analyzing_and_manipulating_DTDs__51648_51815.png DtdAnalyzer__A_tool_for_analyzing_and_manipulating_DTDs__51816_52019.png DtdAnalyzer__A_tool_for_analyzing_and_manipulating_DTDs__52020_52079.png DtdAnalyzer__A_tool_for_analyzing_and_manipulating_DTDs__52080_52403.png DtdAnalyzer__A_tool_for_analyzing_and_manipulating_DTDs__52404_52607.png DtdAnalyzer__A_tool_for_analyzing_and_manipulating_DTDs__52608_52667.png DtdAnalyzer__A_tool_for_analyzing_and_manipulating_DTDs__52668_52739.png DtdAnalyzer__A_tool_for_analyzing_and_manipulating_DTDs__52740_53207.png DtdAnalyzer__A_tool_for_analyzing_and_manipulating_DTDs__53208_53579.png DtdAnalyzer__A_tool_for_analyzing_and_manipulating_DTDs__53580_56540.png