Richard's profileRichard Siddaway's BlogPhotosBlogLists Tools Help

Blog


    January 30

    XML to Word

    Found an interesting challenge on the WinIT magazine forum.  Take an XML file

    <recipe name="bread" prep_time="5 mins" cook_time="3 hours">
    <title>Basic bread</title>
    <ingredient amount="8" unit="dL">Flour</ingredient>
    <ingredient amount="10" unit="grams">Yeast</ingredient>
    <ingredient amount="4" unit="dL" state="warm">Water</ingredient>
    <ingredient amount="1" unit="teaspoon">Salt</ingredient>
    <instructions>
    <step>Mix all ingredients together.</step>
    <step>Knead thoroughly.</step>
    <step>Cover with a cloth, and leave for one hour in warm room.</step>
    <step>Knead again.</step>
    <step>Place in a bread baking tin.</step>
    <step>Cover with a cloth, and leave for one hour in warm room.</step>
    <step>Bake in the oven at 180(degrees)C for 30 minutes.</step>
    </instructions>
    </recipe>

    and turn it into a Word document.  I came up with this as a first pass.  Length of the script can be cut by using functions

    ## remove existing document
    $file = "c:\scripts\test.doc"
    if (Test-Path $file){Remove-Item -Path $file}
    ## read xml file
    [xml]$x = Get-Content -Path c:\scripts\test.xml

    ## open word document
    $word = New-Object -ComObject "Word.application"
    $word.visible = $true
    $doc = $word.Documents.Add()
    $doc.Activate()

    ## recipe title
    $word.Selection.Font.Name = "Cambria"
    $word.Selection.Font.Size = "20"
    $word.Selection.TypeText($x.recipe.title)
    $word.Selection.TypeParagraph()

    $word.Selection.Font.Name = "Calibri"
    $word.Selection.Font.Size = "11"
    $word.Selection.TypeText("Preparation Time = $($x.recipe.prep_time)")
    $word.Selection.TypeParagraph()

    $word.Selection.Font.Name = "Calibri"
    $word.Selection.Font.Size = "11"
    $word.Selection.TypeText("Preparation Time = $($x.recipe.cook_time)")
    $word.Selection.TypeParagraph()
    ## ingredients
    $word.Selection.Font.Name = "Cambria"
    $word.Selection.Font.Size = "14"
    $word.Selection.TypeText("Ingredients")
    $word.Selection.TypeParagraph()

    $word.Selection.Font.Name = "Calibri"
    $word.Selection.Font.Size = "11"
    for ($i=0; $i -le ($x.recipe.ingredient.length -1); $i++){

    $ingdnt = $x.recipe.ingredient[$i].amount + " " + $x.recipe.ingredient[$i].unit + " " + $x.recipe.ingredient[$i]."#text" + " " + $x.recipe.ingredient[$i].state
    $word.Selection.TypeText($ingdnt)
    $word.Selection.TypeParagraph()
    }
    ## instructions
    $instructions = $x.recipe.instructions.step | out-string
    $word.Selection.Font.Name = "Cambria"
    $word.Selection.Font.Size = "14"
    $word.Selection.TypeText("Instructions")
    $word.Selection.TypeParagraph()
    $word.Selection.Font.Name = "Calibri"
    $word.Selection.Font.Size = "11"
    $word.Selection.TypeText($instructions)
    $word.Selection.TypeParagraph()

    $doc.SaveAs([REF]$file)
    $Word.Quit()

    The interesting part is working with XML.  By reading it into [xml]$x we create an xmldocument object.  We can then step through the attributes and the elements, convert them to strings where necessary and output to the word document.  If you’ve not played with XML before its worth spending a little time experimenting at the various levels in the document – especially putting them through get-member.

    Couple of points to note.  The way the ingredient element text and the associated attributes are obtained. The way just the instruction steps are retrieved.

    Interesting problem.  For this particular file I found it easier to do this way than using Select-XML from CTP 3.  Select-XML is good for investigating XML but you do have to learn XPath syntax

     

    Technorati Tags: ,

    Comments

    Please wait...
    Sorry, the comment you entered is too long. Please shorten it.
    You didn't enter anything. Please try again.
    Sorry, we can't add your comment right now. Please try again later.
    To add a comment, you need permission from your parent. Ask for permission
    Your parent has turned off comments.
    Sorry, we can't delete your comment right now. Please try again later.
    You've exceeded the maximum number of comments that can be left in one day. Please try again in 24 hours.
    Your account has had the ability to leave comments disabled because our systems indicate that you may be spamming other users. If you believe that your account has been disabled in error please contact Windows Live support.
    Complete the security check below to finish leaving your comment.
    The characters you type in the security check must match the characters in the picture or audio.

    To add a comment, sign in with your Windows Live ID (if you use Hotmail, Messenger, or Xbox LIVE, you have a Windows Live ID). Sign in


    Don't have a Windows Live ID? Sign up

    Trackbacks

    The trackback URL for this entry is:
    http://richardsiddaway.spaces.live.com/blog/cns!43CFA46A74CF3E96!2018.trak
    Weblogs that reference this entry
    • None