Showing posts with label XSD. Show all posts
Showing posts with label XSD. Show all posts

Sunday, May 22, 2011

XML: Recipe Document (part 4)

Now I am working on mocking up a display for a recipe in my xml format. I wanted something that looked like an old fashioned recipe card, and then thought that a checkered tablecloth background would work with the theme. Found the texture on this guy's profile, and it seemed that people were free to use it. Right now, it is a little imperfect, you might notice, for example uneven font sizes and things not lining up, but I was just trying to make something that might look decent inside a nominally small 800x600 limit, and I think for that, it came out all right. I also used some Lorem Ipsum text, a common place holder for where one might eventually put a lot of text. At the end of a first try, I made this:

I used Inkscape for mocking up the image.

XML: Recipe Document (part 3)

Now that we know what kind of information belongs to a recipe, and we have an XSD schema, we can test if it meets our needs in being able to represent a recipe. I saved the XSD from the previous post as recipe.xsd and put it in a folder in which I created the file we will work on today, first_recipe.xml. For this example, I decided to use toast as my recipe. Now, let's start with the basics, open up a text editor and add the following:


This tells our xml file that this recipe is going to follow the definition of a recipe according to the xsd schema file. Now that we have the root element and we have the definition, let's build up the metadata element of the toast recipe.


Nothing here is really surprising, I made sure to use a public domain image, just so everyone knows. All right, the next element. You will notice that my ingredients element looks different than the definition from the previous post, and this is because I discovered some shortcomings in its design yesterday, so let's take a look at the new schema for an ingredient, and then the ingredients for toast:


Ok, notice the attribute element in the new definition. An attribute is a value that is described inside the actual opening tag instead of being defined between the tags. The attribute is the same as the previously defined optional element, same idea, but now it is an attribute. Also, notice that instead of this design being an xsd:sequence, it is now an xsd:all. Sequence forces order; all does not, but when using all, elements may not repeat inside of the complexType. It just so happens that this works for my purposes anyway since all the values have a minimum of 0 (now a minimum of 1) and a maximum of 1. So now let's look at the list of ingredients for toast:


Again, this is pretty straight forward, the recipe requires one slice of bread, and optionally, you may have some butter. The optional tag is itself optional, so we could omit it, for example from the bread, and maybe assume that means that the bread is not optional. Alternatively, we might omit it from the butter, and assume that its absence implies that is optional. In my opinion, since most ingredients are not optional in most recipes, the assumption should be that if the tag is omitted, that it is a required ingredient. Next, is the tiny list of equipment this recipe requires:


Yep, a toaster. Nothing extraordinary to point out about that. Next, we need to look at the procedure node, which it itself remains unchanged, but the definition of the step node has changed, so lets look at the schema for the step node:


Notice, I turned number and image into attributes, also notice that changed the type from sequence to choice, and that choice has minimum and maximum occurrence; This means I can choose to have as many occurrences as I want of first ingredients, then temperatures, followed again by more if I choose. Going back to the discussion on context free grammars and languages from before, we could represent this situation as saying that we want our language to have the following tokens, and the following rules:

TokenCan Become
STEPCHOICE
CHOICECHOICE CHOICE | INGREDIENT | TEMPERATURE | T
INGREDIENTNAME QTY UNIT | NAME UNIT QTY | QTY NAME UNIT | QTY UNIT NAME | UNIT NAME QTY | UNIT QTY NAME
NAMET name T
QTYT quantity T
UNITT unitofmeasure T
TEMPERATUREunsigned integer
Tany string, including the empty string

In this example, all terminating tokens are written in lowercase, and any expandable tokens are written in uppercase, and it can be shown now that any reasonable ordering of elements is possible, such as saying "Set oven to <temperature>300</temperature> degrees and prepare <ingredient>[...]</ingredient>," or "Put <ingredient>[...]</ingredient> into oven when it pre-heats to <temperature>300</temperature> degrees," or indeed any arbitrary ordering and quantity of either set of elements. Now, let's get back to looking at the procedure element:


Notice that the optional tag, which is optional again, was only used on step number 5; the other steps are implied to be mandatory for this recipe, so it isn't necessary to include the optional tag for each of them. Also, most of these steps seem easy to read and write, save for the first step that appears off-puttingly verbose. Realize this: For almost all desired purposes, XML is machine generated. Right now, we are testing the flexibility of the design, so we are more hands on then usually necessary. It does not make it easy to type recipe steps that might include several ingredients right now, (consider what it would look like in a recipe that said "mix flour, eggs, milk, and sugar in a bowl.") But this inconvenience is not a concern, because generally, as said earlier, a program makes an xml document automatically for people, and these fields are also important for demarcating important chunks of information. Say, for example, you decide you would like to write a program that converts a recipe with an arbitrary number of servings to a recipe for specifically 1 or 2 servings? The computer immediately knowing where to look for quantities in the procedure will make writing this software a snap. Or you could use it to convert between metric and imperial measurements, for example, and that is just the tip of the iceberg.

Aside from that, now that we have completely written the recipe for toast, let's take a look at the complete xml document for a toast recipe:


If you are using a text editor with special features, you can probably validate the xml document inside of your editor. Try using Notepad++ and then downloading the xmltools from the built in plugin manager. Then you can do Plugins | XML Tools | Validate Now, and it will tell you if the recipe has any format errors. There are other tools that can work as well. For reference, the current modification of the XSD after the modifications made today is as follows:


Incremental improvements are normal going through the development process, much in the same way I discover every once and again a better way to organize the schema. Now to take a break.

Saturday, May 21, 2011

XML: Recipe Document (part 2)

With the diagram now established it is a lot easier to begin working on the schema document, the XSD file. A schema file basically tells what the expectation for a document are supposed to be, what the names of particular tags are for example and what values are allowed for particular tags. For this part of the project, I am kinda shaky, and I depended a lot on XML Schema Part 0: Primer, a guide to the basic syntax of an XSD document. So, check out the diagram from part 1, and then go on to the next paragraph.

First thing to do is take a look at the tree diagram. A tree diagram starts at the root (like a tree) and from there goes to branches and leaves (like a tree.) My tree has the root on the left side, and the leaves on the right side. The root is the "Recipe" box. Now let's set up the xsd document.

First open a text editor and add the following to our document:


Now, what does this all say? The first tag says this is an XMLSchema; an XSD file, with more information about it with all the tag definitions at the given url. The next tag is an annotation, with a documentation tag. The documentation tag tells us it is written in English, and gives us an idea of what to expect from the rest of the document. This is similar to a comment. After that, we have the matching closing tags and the like to completely close the XSD. Much like XML, XSD needs matching opening or closing tags, or a tag marked especially as being empty instead of a pair by typing a '/' before the last angle bracket. Ok, so that was easy, what next?

We see that the root is a recipe, and that a recipe has, or may contain a metadata section, a list of ingredients, a list of equipment, and a procedure. Because of the large complexity of the Recipe type and some of the children it contains, the recipe should be defined as a complexType, that is, it is made out of a bunch of small parts. For people familiar with OO it is similar to stating that you are creating an object, as opposed to a simple type. So, let's define the Recipe type, and what it contains now.


All right, this says that our defined document is going to have recipe tags, and that the recipe tags are going to require a metadata section and an ingredients section, because there needs to be a minimum of 1 of each, and a max of 1 of each. The metadata is a custom type, but the Ingredients is a set of custom types; a list of singular Ingredient nodes. the equipment and procedure sections are optional, because some recipes don't require anything but the ingredients, and some recipes don't even have steps. (In the case of eating raw foods for example.) Now let's define the Metadata Type.


A few new things. Name is notably defined as a string. In most languages, a string means a group of letters, numbers, and various other characters, as it also does in XML. so we can now type a name like "Cherry Pie" as the name of the recipe. author is also a string, but it can have many 0 or many (unbounded) occurrences. So you can add as many author tags as you like to a single recipe. Servings is defined as a positive integer, that is any counting number starting at one (no decimal places; this might be a weakness in some people's eyes, because some recipes sometimes don't make an even amount of servings. Let's pretend they all do.) the mealtime value is a construct called an enumeration, meaning it can only be one of any of the specifically listed values. You might notice that if that is the case, this design does not let us have recipes for brunch items, or for tea time, a flaw certainly, but there is a benefit in terms of searching and indexing of data. When someone wants to create a recipe, they might decide to create a "dinner" recipe. Someone else might decide to create a "supper" recipe. Semantically, they are the same thing to you and I, but to a computer it is very difficult to understand that they might be the same. After a while, if you find you are too limited by the range of options in the enumeration, you can always just add the extra line in there for Party time recipes if you so desire. Preparation time is a duration type, which is a way of writing how long something takes, exactly what it says, and the last one image is a URI. We can use a URI for storing the web address of an image of what the completed recipe might look like. Although it is possible to embed an image into the xml directly it is not exactly the best possible choice for my purposes.

Next, we will define the ingredient node. The ingredient has a number, in case the order it is used in is important, it has a name, a quantity, a unit of measure, and a value indicating whether or not the ingredient is optional. The ingredient node definition looks like the following:


Interesting things to point out about the definition of an ingredient are the quantity and the optional fields. Quantity is a double type. a double is a double precision floating point number, or a number that allows a decimal, that is, a rational number. Optional is a boolean value. This means it can either be true or false, or if you like, 1 or 0. Also, note that the body of the Ingredient field has the attribute mixed = "true" this means that one can type free flowing text around the fields.

Finally, we define the Step type nodes, which also needs the mixed attribute so that we can organize text around the important parts of an ingredient and temperature. This gives us the following:


No big new surprises here, except it is interesting to note that we can reuse the defined ingredient type from before inside of the free form text. This is a demonstration of reusability, an important idea in software engineering that we should design things to be reused as often as possible. It saves time, and makes fixing potential problems easier, so it is nice to see that XSD files allow this.

Surprisingly, I never knew about this mixed tag until reading the documentation on how to make an XSD file today. Cool stuff. Here is the complete, head to tail version of the XSD file now that it is completely written. Note that I fixed a few mistakes from previous sections as I noticed things were not needed anymore, like getting rid of the ingredient number and so on:


Whew, fun stuff.

XML Self Learning Start

In order to get the ball rolling on this thing, I decided a skill that might be useful that I kinda have, kinda don't have is XML. XML is an abbreviation for eXtensible Markup Language, and it is exactly that; extensible because the definition of an XML document can be changed to meet a particular user need; markup language meaning it is a language for describing information (as opposed to a programming language which is used for automating the problem solving process on a computer.)


Most XML documents are, in the study of formal languages called a Context Free Language, which, if it helps one to visualize, can be thought of as a Tree, in the sense that every piece of information has a singular parent, (save for the parent of the document) and can have none, one, or many children.


Under what circumstances does one generally use XML? XML is used mostly for storing information that will be read again, at some point, by some application. The application might be the same application; it might be an entirely different application. Because of the rules that define XML, it is extremely portable. Because of its portability, it is used often in web applications for sending and receiving information (Another competing format that is growing popular that is used in the same problem space is JSON which I might discuss later.)


In programming, XML is often created through serialization, a process that can be automated to take all the important information of a runtime object and save it into a file. This process is called serialization because it takes information that might be in any particular location and order in memory, and forces it to all be in one location in a specific order (That is serialized). Most programming languages also have deserialization facilities as well, allowing one to instantly put information back into a program from an XML file.


Another advantage to XML is that it can be easy for people to read if they need to read it, allowing software developers and testers to easily spot mistakes, for example, and seeing what might need to be fixed. This is called validation. However, even better than that, XML has built in support for validation through XSD, or XML Schema Document. Using an XSD, one is able to decide what is allowed in a particular document, and what is not allowed. Most XML programming language libraries and several IDEs and enhanced text editors can report if an XML document does not subscribe to noted preconditions, such as missing particular required values, having words in a spot where only numbers should be, or a mistyped phone number, for example. There are some criticisms to XSD and some short comings, but it can be used as a good first step to ensure meeting most preconditions.


In addition to XSD, we can also use XSLT or eXtensible Stylesheet Language Transformations to transform data from one format to another. For example, if information in one program is expected in one format, but the output from another particular program is not in that same format, an XSLT document can be used to automate the process of converting the output into the expected input of another program.


For now, I am going to use Serna Free as my XML editor because it is free and open source and runs on Windows, Mac, and Linux. I have not used it before, but it seemed to have respectable support from a precursory search. Other good editors that may work just as well are Notepad++ or the editors included in your IDE of choice. I chose to try this software because it looks like it might ease the testing of XSD and XSLT along with an XML document. I hope to learn something from this project, and I hope that this will help others as well. If anyone would like to recommend a particularly good free XML editor with built in validation and XSLT testing, please feel free to comment (says I to my absolute zero readership.)