Jump to content
Sign in to follow this  

msWord XML beautifier

Recommended Posts


..so I got Notepad++ but was not working with the xml printing plugin, the online beautifiers would no work all the time, and I wanted like Tidy does with tabs so it looks nice in Scite to look at the code and make my own template for a script I'm working on....very frustrating and time consuming, so, I put this code together. I get in a 10th of a sec. the xml prettified vs. minutes and frustration.

Anyway, how I use it is I drag and drop the word doc. ( saved in XML format ) to scite , copy to the clipboard ( ctrl-A, ctrl-C ) , switch to this code, press F5 and I'm happy

If Not StringInStr($CmdLineRaw, "/ErrorStdOut") And Not @Compiled Then Exit MsgBox( 262144 , @ScriptName, "please run from Editor", 10)

Local $s = ClipGet()
If Not StringInStr($s, '<?mso-application progid="Word.Document"?>') Then Exit MsgBox(262144, StringTrimRight(@ScriptName, 4), "tested only in Word.Document XML" & @CR & @CR & "no changes made to clipboard", 20)
Local $sOut = msWordXML_Beautify($s, 2) ; 2=return as beautified string, 1=ConsoleWrite beautified string, 0=return beautified array
MsgBox(262144, StringTrimRight(@ScriptName, 4), "clipboard content replaced by beautified XML", 2)

Func msWordXML_Beautify($s, $iEcho = 0)
    Local $iTimer = TimerInit()
    $s = StringReplace($s, @CR, '')
    $s = StringReplace($s, @LF, '')
    Local $a = StringSplit($s, "<")
    Local $b[$a[0] * 2]
    Local $i = 0, $c = ""
    For $x = 1 To $a[0]
        If StringReplace($a[$x], @TAB, "") = "" Then ContinueLoop
        If StringInStr($a[$x], ">") Then $a[$x] = StringReplace($a[$x], @TAB, '')
        $c = StringSplit($a[$x], ">")
        If UBound($c) < 2 Then ContinueLoop
        For $y = 1 To $c[0]
            If $y = 1 Then
                $i += 1
                $b[$i] = "<" & $c[$y] & ">"
                If $c[$y] = "" Then ContinueLoop
                $i += 1
                $b[$i] = $c[$y]
    ReDim $b[$i + 1]
    $b[0] = $i
    For $x = 3 To $b[0]
        If Not StringInStr($b[$x - 1], ">") Then
            $b[$x] = $b[$x - 2] & $b[$x - 1] & $b[$x]
            $b[$x - 2] = "<>"
            $b[$x - 1] = "<>"
    Dim $c[$b[0] + 1]
    $i = 0
    For $x = 1 To $b[0]
        If $b[$x] = "<>" Then ContinueLoop
        $i += 1
        $c[$i] = $b[$x]
    $b = $c
    $c = ""
    ReDim $b[$i + 1]
    $b[0] = UBound($b) - 1
    Local $tabs = ""
    For $x = 1 To $b[0]
        $b[$x] = StringStripWS($b[$x], 3)
        If StringLeft($b[$x], 2) = "<!" Then ContinueLoop
        If StringLeft($b[$x], 2) = "<?" Then ContinueLoop
        If StringLeft($b[$x], 1) = "<" And StringRight($b[$x], 2) = "/>" Then
            $b[$x] = $tabs & $b[$x]
        If StringLeft($b[$x], 2) = "</" And StringRight($b[$x], 1) = ">" Then
            $tabs = StringTrimRight($tabs, 1)
            $b[$x] = $tabs & $b[$x]
        If StringLeft($b[$x], 1) = "<" And StringRight($b[$x], 1) = ">" And Not StringInStr($b[$x], '</') Then
            $b[$x] = $tabs & $b[$x]
            $tabs &= @TAB
        $b[$x] = $tabs & $b[$x]
    ConsoleWrite('+ msWordXML_Beautify done in about ' & Round(TimerDiff($iTimer), 5) & ' mSec.' & @CRLF)
    Local $sOut = ""
    If $iEcho Then
        For $x = 1 To $b[0]
            If $iEcho = 1 Then
                ConsoleWrite( $b[$x] & @CRLF )
                $sOut &= $b[$x] & @CRLF
    If $iEcho = 2 Then Return $sOut
    Return $b
EndFunc   ;==>msWordXML_Beautify

..hope it saves time to someone.

Edit 1: it works nice with <?mso-application progid="Excel.Sheet"?>, it may just work with any XML, no clue.

Edit 2: fixed an error in the code

Edited by argumentum

Share this post

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Similar Content

    • macran
      By macran
      I want to generating a XML file (test.xml) like as follow:
      <?xml version="1.0" encoding="GBK"?>
      <!DOCTYPE SCHEMA SYSTEM "HGWSPZJK.dtd">  ;I can not generate this line
      <SCHEMA CRC="HGWSPZ201808_9131011571786229XM_CRC.XML" SSSQ="201808" CHSNAME="HGWSDKQD" NAME="HGWSPZ">

      <TAXPAYER CJRMC="sigmagroup" CJRDM="9131011571786229XM" CJLX="DKZK" RECORDCOUNT="411" SBRQ="2018-08-31" NSRMC="sigmagroup" SWSBH="9131011571786229XM">

      <Record BZ="" JKKADM="2244" JKKAMC="shanghai" SE="5907.82" TFRQ="2018-08-23" FPHM="224420181000752586-L02"/>
      <Record BZ="" JKKADM="2244" JKKAMC="shanghai" SE="4742.4" TFRQ="2018-08-21" FPHM="224420181000743016-L01"/>
      <Record BZ="" JKKADM="2244" JKKAMC="shanghai" SE="18720" TFRQ="2018-08-14" FPHM="224420181000719215-L01"/>
      I use XML.UDF  
      Local $oXMLile=_XML_CreateFile(@ScriptDir&"\test.xml","",True) 
      but there is no function CreateDocumentType 
      It is no effort even I test use 
      Local $doct=$oXMLfile.CreateDocumentType("SCHEMA", null, "HGWSPZJK.dtd", null)
      pls help me thanks.
    • Skeletor
      By Skeletor
      Hi All,
      This is purely an XML Language question. I need to understand how I can add a value/element in between another XML element. 
      Code below shows the XML file. The info tag has the elements already inserted.
      <Configuration xmlns="http://schemas.datacontract.org/2004/07/Modules.Reporting.DataContracts.LineItems" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> <GenConf> <Info>ID, Site, Name , Site_ID</Info> </GenConf> </Configuration> Now, I want to add a value from a node group into this code. Something like below. But the example below does not work.
      Any suggestions?
      <Configuration xmlns="http://schemas.datacontract.org/2004/07/Modules.Reporting.DataContracts.LineItems" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> <GenConf> <Info>ID, Site, a/@id, Name , Site_ID</Info> </GenConf> </Configuration> <ProductName> <a id="Windows Server"/> </ProductName>  
    • bhns
      By bhns
      try it for make flyers old games xml + Gdi, i belive many sources had lost 

    • lavascript
      By lavascript
      I have a Word document containing a 9-column table where row 1 is the column headers. My goal is to read the table into a 2d array, remove some rows, update some fields, and add a few rows to the end. The resulting array will likely be a different length. Next, I want to write the data back into the table. If it's easier, I can write the data to a new document from a template containing the same table header with a blank 2nd row.
      Here's my early attempt:
      Local $oWord = _Word_Create() Local $oDoc = _Word_DocOpen($oWord, $sFile) Local $aData = _Word_DocTableRead($oDoc, 1) $aData[3][5] = "Something else" Local $oRange = _Word_DocRangeSet($oDoc, 0) $oRange = _Word_DocRangeSet($oDoc, $oRange, $wdCell, 9) _Word_DocTableWrite($oRange,$aData) This, unfortunately, writes the entire array into the first cell of row 2. What am I doing wrong?
    • Subz
      By Subz
      Our Microsoft Office Templates shared folder was changed from a DFS share to an Isilon share. example:
      Old Server: \\Domain.com\Office\Templates
      New Server: \\Templates.domain.com\Office\Templates
      The team making the changes overlooked that several hundred thousand documents, had been attached to the old template documents.  So when you open a document which has been attached, it will take a couple of minutes to open, while it tries to locate the old server path.  I've been asked to come in and fix it, so after several hours found that the data is being held in document.zip\word\_rels\settings.xml.rels, I now need to replace the old server path with the new server path.  I didn't want to use dom as that would take too long and found a tool wtc https://github.com/NeosIT/wtc which  works perfectly, takes about 8 minutes to scan a single directory with 4000 documents and fix them.  The problem is the documents are all held on sharepoint and they want to retain the file timestamp, which is easy enough, but they also don't want to keep the "Modified By" apparently they don't like seeing all the documents appearing as "Modified by: Subz"  Anyone know of way to retain the "Modified By" info,