Intro to Word XML Part 3: Using Your Own Schema
When we built the support for customer defined schemas into Word 2003 there were a couple scenarios we had in mind. The main goal though was that we wanted people to take existing Word documents and existing Word solutions, and make them more powerful. There has long been support for bookmarks, which have some similarities to the XML support, but that just wasn't enough. The custom XML support finally gave developers the ability to add structure to a Word document and to program against it. Did you know that once you add you're XML to a Word document, you can capture events when a user moves in or out of that element? Did you know that you can use XPath queries to navigate the Word document based on your XML, and get a Word range object as a result? There is a ton of power here, even if your end goal has nothing to do with XML. Of course you can always save out as XML and use that data in some other process, but even if you don't care about getting XML out, the XML support still makes building solutions easier.
Add your XML to a Word document
In order to try out these examples, you'll need to either have a version of Word that supports customer XML, or use the online labs. As I've pointed out, there are a number of uses for the custom XML support in Word. You can use it to bring data into Word, as well as get data out of Word. You can also use it in an existing document to simply make your solutions easier to build and more robust. Today I wanted to just give a quick introduction to getting custom XML into Word. In my first introductory post on Word XML, I showed you how to create a simple Word document. Let's take that example and look at how you could add your own XML to that as well. We'll start with the basic XML file:
<?xml version="1.0"?>
<w:wordDocument
xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml">
<w:body>
<w:p>
<w:r>
<w:rPr>
<w:b/>
</w:rPr>
<w:t xml:space="preserve">Name: </w:t>
</w:r>
<w:r>
<w:t>Brian Jones</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:rPr>
<w:b/>
</w:rPr>
<w:t xml:space="preserve">Occupation: </w:t>
</w:r>
<w:r>
<w:t>Program Manager</w:t>
</w:r>
</w:p>
</w:body>
</w:wordDocument>
If you open this in Word, you'll see that it's pretty easy to look at the file and understand what's being described. A human can easily see what the name and occupation is. If you were building a solution though to pull the information and do something smart with it, it would be a bit harder. That's where the XML support comes in. We can mark this up with our own XML, and our solution can then act on that instead. Let's add a new namespace called "http://jonesxml.com/schemas/example1" to the file and give it the prefix: "s:". Our root element should now look like this:
<w:wordDocument xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:s="http://jonesxml.com/schemas/example1">
The next thing to do is to add the XML from our schema to the file. There are three elements in our schema: employee, name, and occupation. In order to add these to our file, we just put them inline with the Word XML like this:
<?xml version="1.0"?>
<w:wordDocument xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:s="http://jonesxml.com/schemas/example1">
<w:body>
<s:employee>
<w:p>
<w:r>
<w:rPr>
<w:b/>
</w:rPr>
<w:t xml:space="preserve">Name: </w:t>
</w:r>
<s:name>
<w:r>
<w:t>Brian Jones</w:t>
</w:r>
</s:name>
</w:p>
<w:p>
<w:r>
<w:rPr>
<w:b/>
</w:rPr>
<w:t xml:space="preserve">Occupation: </w:t>
</w:r>
<s:occupation>
<w:r>
<w:t>Program Manager</w:t>
</w:r>
</s:occupation>
</w:p>
</s:employee>
</w:body>
</w:wordDocument>
Go ahead and open this file in Word. If you don't have the tag view turned on, you probably won't notice any difference yet. Press "CTRL + Shift + X" and you can toggle the XML tag view on and off. Notice that there are XML tags for all three of your elements. You can bring up the XML structure pane as well by pressing "Shift + F1" and on the task pane selector dropdown select the XML structure pane. You can also specify in your XML file directly whether or not you want the XML tags to show. In the document properties, you can set the showXMLTags element. To specify that they always show when the file is opened, just update your file like this:
<?xml version="1.0"?>
<w:wordDocument xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:s="http://jonesxml.com/schemas/example1">
<w:docPr>
<w:showXMLTags w:val="on"/>
</w:docPr>
<w:body>
<s:employee>
<w:p>
<w:r>
<w:rPr>
<w:b/>
</w:rPr>
<w:t xml:space="preserve">Name: </w:t>
</w:r>
<s:name>
<w:r>
<w:t>Brian Jones</w:t>
</w:r>
</s:name>
</w:p>
<w:p>
<w:r>
<w:rPr>
<w:b/>
</w:rPr>
<w:t xml:space="preserve">Occupation: </w:t>
</w:r>
<s:occupation>
<w:r>
<w:t>Program Manager</w:t>
</w:r>
</s:occupation>
</w:p>
</s:employee>
</w:body>
</w:wordDocument>
You can also specify that they should not show up by setting the attribute value to "off".
Basic use of the object model
OK, one last thing for this post as it's already getting too long. I wanted to quickly show how you can use the object model to take advantage of the XML structure. Image you wanted to write a solution that changed the employee name. It's really simple. Open the file in Word and bring up VBE (ALT + F11). In the immediate window (CTRL + G) type the following:
activedocument.SelectSingleNode("//s:name", "xmlns:s='http://jonesxml.com/schemas/example1'").Range.Text = "Your name"
Hit enter and go back to your document. Notice that the value of the name is now changed. You can move that name element anywhere in your file and this solution will still work fine. If future examples I'll show how you can capture events on these elements to build a pretty rich solution without a ton of code.
-Brian