Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

how to read values in this xml file?

2 views
Skip to first unread message

Rich P

unread,
Nov 19, 2009, 5:23:28 PM11/19/09
to
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" DefaultTargets="Build"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
</PropertyGroup>
</Project>


I am using the following code to read the value in the <ProductVersion>
tag in the above xml file:

----------------------------------
XPathDocument doc = new XPathDocument(myxml.xml);
XPathNavigator nav = doc.CreateNavigator();

XPathExpression expr;
expr = nav.Compile("/Project/PropertyGroup/ProductVerion");
XPathNodeIterator iterator = nav.Select(expr);

iterator.MoveNext(); //actually in a loop
XPathNavigator nav2 = iterator.Current.Clone();
Console.WriteLine("version " + nav2.Value.ToString());
----------------------------------

this works if I leave out

xmlns="http://schemas.microsoft.com/developer/msbuild/2003"

from the <Project> tag. But the actual file that I am trying to read
contains the "xmlns ..." text and my routine won't read the
ProductVersion tag. I am hoping that the methods I am using here are
outdated and there are newer methods/classes I could use to perform this
read. Any help appreciated.

Thanks

Rich

*** Sent via Developersdex http://www.developersdex.com ***

Message has been deleted

Peter Duniho

unread,
Nov 19, 2009, 7:34:11 PM11/19/09
to
Rich P wrote:
> [...]

> ----------------------------------
> XPathDocument doc = new XPathDocument(myxml.xml);
> XPathNavigator nav = doc.CreateNavigator();
>
> XPathExpression expr;
> expr = nav.Compile("/Project/PropertyGroup/ProductVerion");
> XPathNodeIterator iterator = nav.Select(expr);
>
> iterator.MoveNext(); //actually in a loop
> XPathNavigator nav2 = iterator.Current.Clone();
> Console.WriteLine("version " + nav2.Value.ToString());
> ----------------------------------
>
> this works if I leave out
>
> xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
>
> from the <Project> tag. But the actual file that I am trying to read
> contains the "xmlns ..." text and my routine won't read the
> ProductVersion tag. [...]

I think the problem you're running into is that with the xmlns
declaration, the element names actually implicitly include that XML
namespace, and so the namespace has to be included in the fully
qualified element name for your XPath expressions.

Unfortunately, as far as I know, there's no way to get XPathNavigator to
handle this automatically, because while the namespace itself is the URI
declared in the "xmlns" attribute, XPath requires a prefix, not the full
URI. You can't just stick the URI in front of the element name and have
it work.

But, you can get it to work in a "semi-automatic" way by creating an
XmlNamespaceManager that maps a prefix of your choosing to the URI for
the namespace, and then use that prefix in your XPath expression.

See below for a concise-but-complete code example that demonstrates the
technique (my apologies in advance for broken string literals...they
tend not to survive newsgroup copy-and-paste very well, but I assume you
can make the necessary edits after the fact if there's a problem).

You can also read about it here:
http://msdn.microsoft.com/en-us/library/e5t11tzt.aspx

If that doesn't answer your question, you really need to post a
concise-but-complete code example yourself, so that we can see what your
code is really doing and why it doesn't work.

Pete


using System;
using System.Xml.XPath;
using System.Xml;
using System.IO;

namespace TestXmlWithNamespace
{
class Program
{
static void Main(string[] args)
{
string strXml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
"<Project ToolsVersion=\"3.5\" DefaultTargets=\"Build\"" +
"
xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">" +
"<PropertyGroup>" +
"<ProductVersion>9.0.30729</ProductVersion>" +
"<SchemaVersion>2.0</SchemaVersion>" +
"<OutputType>WinExe</OutputType>" +

"<AppDesignerFolder>Properties</AppDesignerFolder>" +
"</PropertyGroup>" +
"</Project>";

XPathDocument doc = new XPathDocument(new
StringReader(strXml));
XPathNavigator nav = doc.CreateNavigator();
XmlNamespaceManager manager = new
XmlNamespaceManager(nav.NameTable);

manager.AddNamespace("default",
"http://schemas.microsoft.com/developer/msbuild/2003");

foreach (XPathNavigator xpath in
nav.Select("/default:Project/default:PropertyGroup/default:ProductVersion",
manager))
{
Console.WriteLine(xpath.Name);
}

Console.WriteLine("done");
Console.ReadLine();
}
}
}

Tom Shelton

unread,
Nov 19, 2009, 7:41:50 PM11/19/09
to
On 2009-11-19, Rich P <rpn...@aol.com> wrote:
><?xml version="1.0" encoding="utf-8"?>
><Project ToolsVersion="3.5" DefaultTargets="Build"
> xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
> <PropertyGroup>
> <ProductVersion>9.0.30729</ProductVersion>
> <SchemaVersion>2.0</SchemaVersion>
> <OutputType>WinExe</OutputType>
> <AppDesignerFolder>Properties</AppDesignerFolder>
> </PropertyGroup>
></Project>
>
>
<snip>

>
> *** Sent via Developersdex http://www.developersdex.com ***

Well, if you using 2008, then I would do it something like this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.IO;

namespace ConsoleApplication52
{
class Program
{
private const string Xml = @"<?xml version=""1.0"" encoding=""utf-8""?>


<Project ToolsVersion=""3.5"" DefaultTargets=""Build"" xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
<PropertyGroup>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
</PropertyGroup>

</Project>";

static void Main ( string[] args )
{
XNamespace dName = "http://schemas.microsoft.com/developer/msbuild/2003";
XElement doc = XElement.Load ( new StringReader ( Xml ) );
var s = ( from version in doc.Descendants ( dName + "ProductVersion" ) select version.Value ).FirstOrDefault ();
Console.WriteLine ( s );
}
}
}

--
Tom Shelton

Paul

unread,
Nov 20, 2009, 10:03:44 AM11/20/09
to
I would use the reader anyway, should be far better performance wise.


"Rich P" <rpn...@aol.com> wrote in message
news:%23ecRsbW...@TK2MSFTNGP04.phx.gbl...

Rich P

unread,
Nov 20, 2009, 12:23:25 PM11/20/09
to
Thanks all for your replies. The manager suggestion worked as
advertised and the xml.linq method also worked well and less code.

Now I have a wealth of methods for reading xml. Question: is it
accurate that the XmlTextReader method will outperform xml.linq? I do
have hundreds (if not more) xml files that I will have to read.

Thanks again all for the help.

Peter Duniho

unread,
Nov 20, 2009, 1:46:27 PM11/20/09
to
Rich P wrote:
> Thanks all for your replies. The manager suggestion worked as
> advertised and the xml.linq method also worked well and less code.
>
> Now I have a wealth of methods for reading xml. Question: is it
> accurate that the XmlTextReader method will outperform xml.linq? I do
> have hundreds (if not more) xml files that I will have to read.

It just depends. In theory, the linear behavior of the XmlTextReader is
more efficient and thus faster. But it's also less convenient to use,
and for small files, so much of the time cost of dealing with the file
is in just the basic processing of opening the file, reading something
from it, and closing it, costs that are incurred no matter what
technique you use to access the data in the file.

And of course, if you need random access to the data in the file,
XmlTextReader becomes unwieldy and potentially much less efficient.

If you have long files, and you know in advance that the data you need
to access is always close to the beginning of the file, I would say that
XmlTextReader is going to be a slam dunk for better performance. But
otherwise, there are too many variables to predict whether there will be
a significant, or any, improvement in performance. You're better off
using the API that is most convenient, and then watching for performance
issues in case they do occur.

Pete

0 new messages