none
PowerShell: Appending an XML element re-writes existing elements at the same node? (Office) RRS feed

  • Question

  • I don't think that this is specific to the XML I'm working with, but just in case, I'm using PowerShell scripts to modify the contents of Office 2010 ribbons.  I use a snippet similar to the below to add a control to a custom group:

    $OfficeUI= New-Object XML
    $UIFile=$env:localappdata + '\Microsoft\Office\olkmailitem.officeui'
    $OfficeUI.Load($UIFile)
    $NSM=New-Object System.Xml.XmlNamespaceManager $OfficeUI.NameTable
    $NSM.AddNamespace('mso','http://schemas.microsoft.com/office/2009/07/customui')
    $mso=$NSM.LookupNamespace('mso')
    $TAB=$OfficeUI.customUI.ribbon.tabs.tab | ?{$_.idQ -like 'mso:TabInsert'}
    $IncludeGroup=$TAB.group | ? {$_.id -like 'MyCustomInsertInclude'}
    $Button=$OfficeUI.CreateElement('mso:control',$mso)
    $attr=$OfficeUI.CreateAttribute('idQ')
    $attr.value='mso:CalendarButton'
    $QUIET=$Button.Attributes.Append($attr)
    $attr=$OfficeUI.CreateAttribute('visible')
    $QUIET=$Button.Attributes.Append($attr)
    $QUIET=$IncludeGroup.AppendChild($Button)

    This works exactly as expected and gives me this chunk of XML (just the relevant section:

        <mso:tabs>
          <mso:tab idQ="mso:TabInsert">
            <mso:group idQ="mso:GroupInclude" visible="false" />
            <mso:group id="MyCustomInsertInclude" label="Include" insertBeforeQ="mso:GroupInsertTables" autoScale="true">
              <mso:control idQ="mso:CalendarButton" visible="true" />
            </mso:group>
          </mso:tab>

    However, I want to add some additional controls:

    $Button2=$OfficeUI.CreateElement('mso:control',$mso)
    $attr=$OfficeUI.CreateAttribute('idQ')
    $attr.value='mso:AttachFile'
    $QUIET=$Button2.Attributes.Append($attr)
    $attr=$OfficeUI.CreateAttribute('visible')
    $QUIET=$Button2.Attributes.Append($attr)
    $QUIET=$IncludeGroup.AppendChild($Button2)

    This results in the following XML snippet:

        <mso:tabs>
          <mso:tab idQ="mso:TabInsert">
            <mso:group idQ="mso:GroupInclude" visible="false" />
            <mso:group id="MyCustomInsertInclude" label="Include" insertBeforeQ="mso:GroupInsertTables" autoScale="true">
              <mso:control idQ="mso:AttachFile" visible="true" />
              <mso:control idQ="mso:AttachFile" visible="true" />
            </mso:group>
          </mso:tab>

    Errrr....huh?  Why did THAT happen?  It doesn't matter how many controls I add, all of them have the attributes of the last one added.  Oddly, it also doesn't matter if I write a SEPARATE script to add the next control....all of the controls in the group I add to are re-written as the control I added.

    Is  this something basic I just dunno about Powershell, XML, or both?


    • Edited by Eric-FC Wednesday, January 18, 2017 6:41 PM
    • Moved by Bill_Stewart Friday, February 17, 2017 7:12 PM Move to more appropriate forum
    Wednesday, January 18, 2017 6:40 PM

All replies

  • I looked at this and find that MS seems to have a bad schema.  The attributes add incorrectly.  I have seen this before when MS deosn't want us to edit these files or there is another namespace tht is supplied by the application that resolves issues.  This may allow the app to create variations on the base schema.

    On Office 2016 OneClick it behaves even worse.

    I suggest posting in the Office Developers forum.  They may know what the trick is here.

    If I run your code I get the following:

    <mso:customUI xmlns:mso="http://schemas.microsoft.com/office/2009/07/customui">
      <mso:ribbon>
        <mso:qat />
        <mso:tabs>
          <mso:tab idQ="mso:TabMail">
            <mso:tab idQ="mso:TabInsert">
              <mso:group idQ="mso:GroupInclude" visible="false" />
              <mso:group id="MyCustomInsertInclude" label="Include" insertBeforeQ="mso:GroupInsertTables" autoScale="true">
                <mso:control idQ="mso:CalendarButton" visible="true" />
                <mso:control idQ="mso:AttachFile" xmlns:mso=" xmlns xml mso" />
              </mso:group>
            </mso:tab>
            <mso:group idQ="mso:GroupOfficeApps" visible="false" />
          </mso:tab>
        </mso:tabs>
      </mso:ribbon>
    </mso:customUI>

    Note the crap:  <mso:control idQ="mso:AttachFile" xmlns:mso=" xmlns xml mso" />

    This is an xml fragment that is intended to be loaded into a larger piece of XML and enclosed in other namespaces.


    \_(ツ)_/


    • Edited by jrv Wednesday, January 18, 2017 7:52 PM
    Wednesday, January 18, 2017 7:48 PM
  • FWIW, I still have no idea why this behaves this way, but I was able to make this work right simply by using .InserAfter instead of .Append.

    $Button2=$OfficeUI.CreateElement('mso:control',$mso)
    $attr=$OfficeUI.CreateAttribute('idQ')
    $attr.value='mso:AttachItem'
    $QUIET=$Button2.Attributes.Append($attr)
    $attr=$OfficeUI.CreateAttribute('visible')
    $QUIET=$Button2.Attributes.Append($attr)
    $QUIET=$IncludeGroup.InsertAfter($Button2,$Button1)
    $Button2.visible='true'

    Friday, February 17, 2017 9:55 PM