问题
I have some XML:
<?xml version="1.0" ?>
<Project ToolsVersion="4.0">
<PropertyGroup Condition="'$(key)'=='1111'">
<Key>Value</Key>
</PropertyGroup>
</Project>
Note: This isn't the actual XML i'm using, it's just prettier and shorter, and demonstrates the problem.
Using MSXML i can query for nodes:
IXMLDOMNode node = doc.selectSingleNode("//PropertyGroup/@Condition");
And it works fine:
Condition="'$(key)'=='1111'"
But that's not really the XML i have
In reality the XML i have contains a namespace declaration:
xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
making the actual XML document:
<?xml version="1.0" ?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(key)'=='1111'">
<Key>Value</Key>
</PropertyGroup>
</Project>
Now my query:
IDOMNode node = doc.selectSingleNode("//PropertyGroup/@Condition");
returns no matching nodes.
How do i query the default namespace using MSXML?
Note:
i already know how to query the non-default namespace in xml; you use:
doc.setProperty("SelectionNamespaces", "xmlns="http://schemas.microsoft.com/developer/msbuild/2003");
i already know how to query the default namespace in .NET. You use the namespace manager, give the default namespace a name, then query using that name, then you can query the non-default namespace since it's no longer default
i can just delete the offensive
xmlns
text from the XML string i receive, but i'd rather "do it the right way"
How do i query the "default", or "unnamed" namespace using MSXML?
Note: In reality the XML i am using the SQL Server's XML ShowPlan output:
<?xml version="1.0" encoding="UTF-16" standalone="yes"?>
<ShowPlanXML Version="1.1" Build="10.50.1600.1"
xmlns="http://schemas.microsoft.com/sqlserver/2004/07/showplan">
<BatchSequence>
<Batch>
...
</Batch>
</BatchSequence>
</ShowPlanXML>
Again you can see the offending namespace declaration. Deleting it works, but that's tedious.
What else have you tried?
i also tried setting the SelectionNamespace:
doc.setProperty('SelectionNamespaces',
'xmlns="http://schemas.microsoft.com/developer/msbuild/2003"');
as Microsoft hints at in a KB article.
How do i get the default namespace?
In reality i don't care about namespaces. My query makes sense, and i want it to work. So, Another approach to the question might be:
How can i query the default namespace whether, or not, and no matter what, that namespace name is (or isn't)?
Note: msxml is native code, and using it from a native Win32 compiler (i.e. no .NET framework or CLR)
回答1:
Explicitly give the namespace a name when you add it to the SelectionNamespaces
:
doc.setProperty("SelectionNamespaces",
"xmlns:peanut='http://schemas.microsoft.com/developer/msbuild/2003'");
and then query using that namespace:
IDOMNode node = doc.selectSingleNode("//peanut:PropertyGroup/@Condition");
You can give that namespace any abbreviation name you want (peanut
in this case). And then use the abbreviation as prefix (peanut:PropertyGroup
in this case).
Earlier suggestions
I would try moving to Xml.Linq
.
Here is a sample (with a namespace).
try
{
XDocument xDoc1 = XDocument.Parse("<?xml version=\"1.0\" ?><Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\"><PropertyGroup Condition=\"'$(key)'=='1111'\"><Key>Value</Key></PropertyGroup></Project>");
XNamespace ns1 = XNamespace.Get("http://schemas.microsoft.com/developer/msbuild/2003");
var list1 = from list in xDoc1.Descendants(ns1 + "Project")
from item in list.Elements(ns1 + "PropertyGroup")
/* where item.Element(ns + "HintPath") != null */
where item.Attribute("Condition") != null
select new
{
MyCondition = item.Attribute("Condition") == null ? "Not Here!" : item.Attribute("Condition").Value,
MyFake = item.Attribute("DoesNotExistTest") == null ? "Not Here Sucker!" : item.Attribute("DoesNotExistTest").Value
};
foreach (var v in list1)
{
Console.WriteLine(v.ToString());
}
XDocument xDoc2 = XDocument.Parse("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"yes\"?> <ShowPlanXML Version=\"1.1\" Build=\"10.50.1600.1\" xmlns=\"http://schemas.microsoft.com/sqlserver/2004/07/showplan\"> <BatchSequence> <Batch>Something I Threw In Here</Batch> </BatchSequence> </ShowPlanXML> ");
XNamespace ns2 = XNamespace.Get("http://schemas.microsoft.com/sqlserver/2004/07/showplan");
var list2 = from list in xDoc2.Descendants(ns2 + "ShowPlanXML")
from item in list.Elements(ns2 + "BatchSequence")
/* where item.Attribute("Condition") != null */
where item.Element(ns2 + "Batch") != null
select new
{
BatchValue = (item.Element(ns2 + "Batch") == null) ? string.Empty : item.Element(ns2 + "Batch").Value
};
foreach (var v in list2)
{
Console.WriteLine(v.ToString());
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
来源:https://stackoverflow.com/questions/16490839/how-to-query-default-namespace-with-msxml