2010-05-10 3 views
1

J'ai du mal à trouver comment utiliser par défaut namespaces avec XmlDataProvider et XPath liaisons.Les liaisons XmlDataProvider et XPath n'autorisent pas l'espace de noms par défaut des données XML?

Il existe un ugly answer utilisant le nom local <Binding XPath="*[local-name()='Name']" /> mais ce n'est pas acceptable pour le client qui souhaite que ce code XAML soit hautement maintenable. La solution de secours consiste à les forcer à utiliser des espaces de noms autres que ceux par défaut dans le rapport XML, mais cela est une solution indésirable.

Le fichier de rapport XML ressemble à ceci. Cela ne fonctionnera que si je supprime xmlns="http://www.acme.com/xml/schemas/report donc il n'y a pas d'espace de noms par défaut.

<?xml version="1.0" encoding="utf-8"?> 
<?xml-stylesheet type='text/xsl' href='PreviewReportImages.xsl'?> 
<Report xsl:schemaLocation="http://www.acme.com/xml/schemas/report BlahReport.xsd" xmlns:xsl="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.acme.com/xml/schemas/report"> 
    <Service>Muncher</Service> 
    <Analysis> 
    <Date>27 Apr 2010</Date> 
    <Time>0:09</Time> 
    <Authoriser>Service Centre Manager</Authoriser> 

que je présente dans une fenêtre avec XAML:

<Window x:Class="AcmeTest.ReportPreview" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="ReportPreview" Height="300" Width="300" > 
    <Window.Resources> 
     <XmlDataProvider x:Key="Data"/> 
    </Window.Resources> 
    <StackPanel Orientation="Vertical" DataContext="{Binding Source={StaticResource Data}, XPath=Report}"> 
     <TextBlock Text="{Binding XPath=Service}"/> 
    </StackPanel> 
</Window> 

avec code-behind utilisé pour charger un XmlDocument dans le XmlDataProvider (semble la seule façon d'avoir le chargement d'un fichier ou un objet variable lors de l'exécution).

public partial class ReportPreview : Window 
{ 
    private void InitXmlProvider(XmlDocument doc) 
    { 
     XmlDataProvider xd = (XmlDataProvider)Resources["Data"]; 
     xd.Document = doc; 
    } 

    public ReportPreview(XmlDocument doc) 
    { 
     InitializeComponent(); 
     InitXmlProvider(doc); 
    } 

    public ReportPreview(String reportPath) 
    { 
     InitializeComponent(); 

     var doc = new XmlDocument(); 
     doc.Load(reportPath); 
     InitXmlProvider(doc); 
    } 
} 
+1

Sans test, vous devriez pouvoir utiliser un XmlNamespaceManager dans le cadre de la liaison; alors vous devrez utiliser un préfixe, mais cela devrait fonctionner. – p00ya

+0

Ouais, forcer un préfixe est mon fallback mais cela signifie que beaucoup de scripts externes XSLT doivent être modifiés, ce qui est satisfaisant avec l'espace de noms par défaut. –

+0

doh - voir ma réponse ci-dessous! –

Répondre

2

Je ne l'avais pas rendu compte que je ne ai pas besoin d'ajouter un préfixe aux données XML client, il suffit d'utiliser un préfixe dans mes expressions XPath qui correspond à la même URI que l'espace de noms par défaut (évident quand je dormi dessus!). Donc, le correctif était d'ajouter un mappage d'espace de noms comme indiqué ici, notez l'utilisation du préfixe r: sur les éléments.

<Window x:Class="AcmeTest.ReportPreview" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="ReportPreview" Height="300" Width="300" > 
    <Window.Resources> 
     <XmlDataProvider x:Key="Data"> 
      <XmlDataProvider.XmlNamespaceManager> 
       <XmlNamespaceMappingCollection> 
        <XmlNamespaceMapping 
         Uri="http://www.acme.com/xml/schemas/report" 
         Prefix="r" /> 
       </XmlNamespaceMappingCollection> 
      </XmlDataProvider.XmlNamespaceManager> 
     </XmlDataProvider> 
    </Window.Resources> 
    <StackPanel Orientation="Vertical" DataContext="{Binding Source={StaticResource Data}, XPath=Report}"> 
     <TextBlock Text="{Binding XPath=r:Service}"/> 
     <TextBlock Text=" "/> 
     <TextBlock Text="{Binding XPath=r:Name/r:Last}"/> 
    </StackPanel> 
</Window> 
Questions connexes