Question

Son et un .vbproj ressemble à ceci

<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup>
        <ProjectGuid>15a7ee82-9020-4fda-a7fb-85a61664692d</ProjectGuid>

tout ce que je veux est le ProjectGuid mais il ne fonctionne pas quand un espace de noms est là ...

 Dim xmlDoc As New XmlDocument()
 Dim filePath As String = Path.Combine(mDirectory, name + "\" + name + ".vbproj")
 xmlDoc.Load(filePath)
 Dim value As Object = xmlDoc.SelectNodes("/Project/PropertyGroup/ProjectGuid")

Que puis-je faire pour résoudre ce problème?

Était-ce utile?

La solution

La meilleure façon de faire des choses comme ça (à mon humble avis) est de créer un gestionnaire d'espace de noms. Ceci peut être utilisé pour indiquer l'appel SelectNodes les URL d'espace de noms sont connectés à qui préfixes. Je normalement mis en place une propriété statique qui renvoie une instance appropriée comme celui-ci (il est C #, vous devrez traduire):

private static XmlNamespaceManager _nsMgr;
public static XmlNamespaceManager NsMgr
{
  get
  {
    if (_nsMgr == null)
    {
      _nsMgr = new XmlNamespaceManager(new NameTable());
      _nsMgr.AddNamespace("msb", "http://schemas.microsoft.com/developer/msbuild/2003");
    }
    return _nsMgr;
  }
}

Je ne comporter qu'un seul espace de noms ici, mais vous pouvez avoir plusieurs. Ensuite, vous pouvez sélectionner à partir du document comme celui-ci:

Dim value As Object = xmlDoc.SelectNodes("/msb:Project/msb:PropertyGroup/msb:ProjectGuid", NsMgr)

Notez que tous les éléments se trouvent dans l'espace de noms spécifié.

Autres conseils

Je serais probablement enclin à aller avec Bartek * solution d'espace de noms, mais une solution de XPath générale est:

//*[local-name()='ProjectGuid']

** depuis la réponse de Bartek a disparu, je vous recommande de Teun (qui est en fait plus approfondie) *

Ce problème a été ici plusieurs fois déjà.

Soit vous travaillez avec espace de nom agnostique expressions XPath (non recommandé pour sa gaucherie et le potentiel de faux positifs - <msb:ProjectGuid> et <foo:ProjectGuid> sont les mêmes pour cette expression):

//*[local-name() = 'ProjectGuid']

ou que vous faites la bonne chose et d'utiliser un XmlNamespaceManager pour enregistrer l'URI d'espace de sorte que vous pouvez inclure un préfixe d'espace de noms dans votre XPath:

Dim xmlDoc As New XmlDocument()
xmlDoc.Load(Path.Combine(mDirectory, name, name + ".vbproj"))

Dim nsmgr As New XmlNamespaceManager(xmlDoc.NameTable)
nsmgr.AddNamespace("msb", "http://schemas.microsoft.com/developer/msbuild/2003")

Dim xpath As String = "/msb:Project/msb:PropertyGroup/msb:ProjectGuid"
Dim value As Object = xmlDoc.SelectNodes(xpath, nsmgr)

Il vous suffit d'enregistrer ce XML associé et les espaces de noms avec un préfixe, pour faire le travail de recherche. Créer et passer un gestionnaire d'espace de noms en tant que second paramètre lors de la sélection des noeuds:

Dim ns As New XmlNamespaceManager ( xmlDoc.NameTable )
ns.AddNamespace ( "msbuild", "http://schemas.microsoft.com/developer/msbuild/2003" )
Dim value As Object = xmlDoc.SelectNodes("/msbuild:Project/msbuild:PropertyGroup/msbuild:ProjectGuid", ns)

Une façon est d'utiliser des extensions + NamespaceManager.
Le code est en VB, mais est vraiment facile à traduire en C #.

Imports System.Xml
Imports System.Runtime.CompilerServices

Public Module Extensions_XmlHelper

    'XmlDocument Extension for SelectSingleNode
    <Extension()>
    Public Function _SelectSingleNode(ByVal XmlDoc As XmlDocument, xpath As String) As XmlNode
        If XmlDoc Is Nothing Then Return Nothing

        Dim nsMgr As XmlNamespaceManager = GetDefaultXmlNamespaceManager(XmlDoc, "x")
        Return XmlDoc.SelectSingleNode(GetNewXPath(xpath, "x"), nsMgr)
    End Function

    'XmlDocument Extension for SelectNodes
    <Extension()>
    Public Function _SelectNodes(ByVal XmlDoc As XmlDocument, xpath As String) As XmlNodeList
        If XmlDoc Is Nothing Then Return Nothing

        Dim nsMgr As XmlNamespaceManager = GetDefaultXmlNamespaceManager(XmlDoc, "x")
        Return XmlDoc.SelectNodes(GetNewXPath(xpath, "x"), nsMgr)
    End Function


    Private Function GetDefaultXmlNamespaceManager(ByVal XmlDoc As XmlDocument, DefaultNamespacePrefix As String) As XmlNamespaceManager
        Dim nsMgr As New XmlNamespaceManager(XmlDoc.NameTable)
        nsMgr.AddNamespace(DefaultNamespacePrefix, XmlDoc.DocumentElement.NamespaceURI)
        Return nsMgr
    End Function

    Private Function GetNewXPath(xpath As String, DefaultNamespacePrefix As String) As String
        'Methode 1: The easy way
        Return xpath.Replace("/", "/" + DefaultNamespacePrefix + ":")

        ''Methode 2: Does not change the nodes with existing namespace prefix
        'Dim Nodes() As String = xpath.Split("/"c)
        'For i As Integer = 0 To Nodes.Length - 1
        '    'If xpath starts with "/", don't add DefaultNamespacePrefix to the first empty node (before "/")
        '    If String.IsNullOrEmpty(Nodes(i)) Then Continue For
        '    'Ignore existing namespaces prefixes
        '    If Nodes(i).Contains(":"c) Then Continue For
        '    'Add DefaultNamespacePrefix
        '    Nodes(i) = DefaultNamespacePrefix + ":" + Nodes(i)
        'Next
        ''Create and return then new xpath
        'Return String.Join("/", Nodes)
    End Function

End Module

Et pour l'utiliser:

Imports Extensions_XmlHelper

......
Dim FileXMLTextReader As New XmlTextReader(".....")
FileXMLTextReader.WhitespaceHandling = WhitespaceHandling.None
Dim xmlDoc As XmlDocument = xmlDoc.Load(FileXMLTextReader)
FileXMLTextReader.Close()
......
Dim MyNode As XmlNode = xmlDoc._SelectSingleNode("/Document/FirstLevelNode/SecondLevelNode")

Dim MyNode As XmlNodeList = xmlDoc._SelectNodes("/Document/FirstLevelNode/SecondLevelNode")

......

Pourquoi ne pas utiliser le // ignorer l'espace de noms:

Dim value As Object = xmlDoc.SelectNodes("//ProjectGuid")

// agit comme wild card à suivre à travers tout entre la racine et le prochain nom de noeud spécifié (i.e. ProjectGuid)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top