Search code examples
c#xmlwpfxpathxmldataprovider

Attribute 'xmlns' in XML file element causes XmlDataProvider to not read past the node


I am trying to read and parse an xml file in xaml and am running into a roadblock because one of the elements (teststandfileheader) in the xml file contains an attribute for 'xmlns' as follows:

<?xml version="1.0" encoding="UTF-8"?>
<teststandfileheader type="Globals" xmlns="http://www.ni.com/TestStand/14.0.0/PropertyObjectFile">
  Test
  <typelist />
  <Data classname="Obj">
    <subprops>
      <DEVBOARD classname="Bool">
        <value>false</value>
      </DEVBOARD>
      <DEVICES_PRESENT_HW classname="Bool">
        <value>true</value>
      </DEVICES_PRESENT_HW>
    </subprops>
  </Data>
</teststandfileheader>

When I set the XPath to just '/', I get all of the text associated with all of the elements. As soon as I attempt to set XPath to something at or below the 'teststandfileheader' level, I do not get any data in return.

Here's the XAML:

<Window x:Class="DOTSDebugSelector.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:tb="http://www.hardcodet.net/taskbar"
        xmlns:local="clr-namespace:DOTSDebugSelector"
        Title="MainWindow" Height="350" Width="525" Visibility="Visible" WindowStyle="ToolWindow">
    <Window.Resources>
        <XmlDataProvider x:Key="TsStationGlobals" x:Name="TsStationGlobals" XPath="/teststandfileheader/Data/subprops" Source="C:\ProgramData\National Instruments\TestStand 2014 (32-bit)\Cfg\StationGlobalsdebug.ini" IsInitialLoadEnabled="True" IsAsynchronous="False">
        </XmlDataProvider>
        <local:TextToBoolConverter x:Key="BoolConverter"/>
        <ContextMenu x:Key="MyMenu">
            <CheckBox Content="USING DEV BOARD" Checked="DevBoard_Checked" IsChecked="{Binding Source={StaticResource TsStationGlobals}, Converter={StaticResource BoolConverter}, UpdateSourceTrigger=PropertyChanged, XPath=DEVBOARD/@value}"></CheckBox>
            <CheckBox Content="USING TEST HARDWARE" Checked="TestHardware_Checked" IsChecked="{Binding Source={StaticResource TsStationGlobals}, Converter={StaticResource BoolConverter}, UpdateSourceTrigger=PropertyChanged, XPath=DEVICES_PRESENT_HW/@value}"></CheckBox>
        </ContextMenu>
    </Window.Resources>
    <Grid>
        <tb:TaskbarIcon IconSource="DOTSIcon.ico" ToolTipText="Click to Setup DOTS Debug Mode" MenuActivation="RightClick"  ContextMenu="{StaticResource MyMenu}" />
        <TextBox HorizontalAlignment="Left" Height="22" Margin="222,124,0,0" TextWrapping="Wrap" Text="{Binding Source={StaticResource TsStationGlobals}, UpdateSourceTrigger=PropertyChanged, XPath=DEVBOARD}" VerticalAlignment="Top" Width="74"/>
        <TextBox HorizontalAlignment="Left" Height="22" Margin="222,151,0,0" TextWrapping="Wrap" Text="{Binding Source={StaticResource TsStationGlobals}, UpdateSourceTrigger=PropertyChanged, XPath=DEVICES_PRESENT_HW}" VerticalAlignment="Top" Width="74"/>
    </Grid>
</Window>

If I remove (or even rename) the attribute in the XML file to something other than 'xmlns' then everything works as expected. Any suggestions on why this may be occurring and how it can be corrected? Also note that I do not control the format of the XML file so the problematic attribute has to stay.


Solution

  • You need to use your namespace in the XPath expression - your current expression isn't correct as there are no elements with that fully qualified name.

    For example, map the namespace to the prefix p and include this in the XPath:

    <XmlDataProvider XPath="/p:teststandfileheader/p:Data/p:subprops" Source="...">
        <XmlDataProvider.XmlNamespaceManager>
            <XmlNamespaceMappingCollection>
                <XmlNamespaceMapping 
                   Uri="http://www.ni.com/TestStand/14.0.0/PropertyObjectFile" 
                   Prefix="p" />
            </XmlNamespaceMappingCollection>
        </XmlDataProvider.XmlNamespaceManager>
    </XmlDataProvider>