2010-11-13 25 views
33

Estoy cargando una cadena a un documento XML que contiene la siguiente estructura:XmlDocument.SelectSingleNode y emisión XMLNamespace

<?xml version="1.0" encoding="utf-8"?> 
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">     
    <ItemGroup> 
    <Compile Include="clsWorker.cs" />   
    </ItemGroup>  
</Project> 

entonces im carga en todo XmlDocument:

XmlDocument xmldoc = new XmlDocument(); 
xmldoc.LoadXml(Xml); 

entonces el siguiente problema situaciones:

XmlNode Node = xmldoc.SelectSingleNode("//Compile"); // return null 

cuando quito el atributo xmlns del elemento raíz (Proyecto) funciona bien, ¿cómo puedo mejorar mi SelectSingleNode para devolver el elemento relevante?

Respuesta

66

Debe utilizar un XmlNamespaceManager en su llamada a SelectSingleNode():

XmlNamespaceManager ns = new XmlNamespaceManager(xmldoc.NameTable); 
ns.AddNamespace("msbld", "http://schemas.microsoft.com/developer/msbuild/2003"); 
XmlNode node = xmldoc.SelectSingleNode("//msbld:Compile", ns); 
+0

Es esto aplica a 'SelectNodes'? –

+0

@ T.S., Sí. 'SelectSingleNode (" xpath ")' es más o menos equivalente a 'SelectNodes (" xpath ") [0]'. –

+0

¿de dónde vino 'msbld'? –

16

pierna derecha desde el documentation of SelectSingleNode() on the MSDN:

Nota
Si la expresión XPath no incluye un prefijo, se se supone que el URI de espacio de nombres es el espacio de nombres vacío. Si su XML incluye un espacio de nombre predeterminado , debe agregar un prefijo y un URI de espacio de nombres al XmlNamespaceManager; de lo contrario, no obtendrá un nodo seleccionado. Para más información, vea Select Nodes Using XPath Navigation.

Y el inmediatamente siguiente ejemplo de código es

XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable); 
nsmgr.AddNamespace("ab", "http://www.lucernepublishing.com"); 
XmlNode book = doc.SelectSingleNode("//ab:book", nsmgr); 

It'snotasifthiswouldbe "hiddenknowledge". ;-)

+0

¡Los enlaces de la última oración valen 100 puntos! – milesma

2

Dado que 'ItemGroup' puede tener varios elementos secundarios 'Compilar', y usted desea específicamente los elementos secundarios 'Compilar' de 'Proyecto/Grupo de elementos', lo siguiente devolverá todos los elementos 'Compilar' deseados y no otros:

XmlDocument projectDoc = new XmlDocument(); 
projectDoc.Load(projectDocPath); 
XmlNamespaceManager ns = new XmlNamespaceManager(projectDoc.NameTable); 
ns.AddNamespace("msbld", "http://schemas.microsoft.com/developer/msbuild/2003"); 
XmlNodeList xnList = projectDoc.SelectNodes(@"/msbld:Project/msbld:ItemGroup/msbld:Compile", ns); 

Tenga en cuenta que la especificación del espacio de nombres 'msbld:' debe preceder a cada nivel de nodo.

+0

upvoted para la advertencia sobre la especificación de espacios de nombres múltiples. – Bora

0

De esta manera no es necesario especificar espacio de nombres:

XmlDocument xmlDoc = new XmlDocument(); 
xmlDoc.LoadXml("your xml"); 
XmlNode node = xmlDoc.SelectSingleNode("/*[local-name() = 'Compile']"); 
XmlNode nodeToImport = xmlDoc2.ImportNode(node, true); 
xmlDoc2.AppendChild(nodeToImport);