1

I have a problem with reading XML which looks as follows:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<connections xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
<connection id="1" odcFile="C:\Users\andr\Documents\My Data Sources\ELITE_MSSQLSERVER2012 PSO Reports.odc" keepAlive="1" name="ELITE_MSSQLSERVER2012 PSO Reports" type="5" refreshedVersion="5" background="1">
<dbPr connection="Provider=MSOLAP.5;Integrated Security=SSPI;Persist Security Info=True;Initial Catalog=PSO;Data Source=ELITE\MSSQLSERVER2012;MDX Compatibility=1;Safety Options=2;MDX Missing Member Mode=Error" command="Reports" commandType="1"/>
<olapPr sendLocale="1" rowDrillCount="1000"/>
</connection>
</connections>

(it's actually a connection.xml file in *.xlsx package). I'm trying to read it with the help of XDocument. I need to change the "odcFile" property. The problem is that it reads the whole thing as a single element without children elements. Why so? XML looks normal. Or maybe there is another workaround to make this?

Andy G
  • 19,232
  • 5
  • 47
  • 69
KorsaR
  • 536
  • 1
  • 10
  • 26
  • What is "it" in "it reads the whole thing"??? Where is the code that you have problem with? – Alexei Levenkov Sep 09 '13 at 23:24
  • "it" means XDocument. I tried var doc = XDocument.Load(connectionsFilePath); var connection = doc.Descendants("connection").First(); – KorsaR Sep 09 '13 at 23:49
  • 1
    So this doesn't work: `d.Element(System.Xml.Linq.XNamespace.Get("http://schemas.openxmlformats.org/spreadsheetml/2006/main") + "connections").Element(System.Xml.Linq.XNamespace.Get("http://schemas.openxmlformats.org/spreadsheetml/2006/main") + "connection").Attribute("odcFile").SetValue("value");` (where d is the `XDocument` and value is the value you want to change `odcFile` to)? – UIlrvnd Sep 10 '13 at 00:31
  • 1
    possible duplicate of [Use Linq to Xml with Xml namespaces](http://stackoverflow.com/questions/2340411/use-linq-to-xml-with-xml-namespaces) or many other "select node with non-default namespace" question. – Alexei Levenkov Sep 10 '13 at 00:59

2 Answers2

1

Try using System.Xml.Document instead, if you can access an actual xml file. Not sure what you mean by "it's actually a connection.xml file in *.xlsx package":

using System.Xml

XmlDocument dom = new XmlDocument();
XmlNone root;

dom.Load(fullpath);

root = dom.DocumentElement;
Brian Ogden
  • 18,439
  • 10
  • 97
  • 176
  • Thanks, this way everything works. But that's kind of strange, as the XDocument is not a third party thing, why it's so buggy then? And as for the *.xlsx package - I'm unzipping the Excel file to dynamicaly change its connection properties. – KorsaR Sep 10 '13 at 00:01
  • 2
    Linq to Xml has many advantages though, you can see an overview [here](http://msdn.microsoft.com/en-us/library/bb387021.aspx). And i don't believe it's a bug, you're probably not using [`XNamespace`](http://msdn.microsoft.com/en-us/library/system.xml.linq.xnamespace.aspx) correctly :). – UIlrvnd Sep 10 '13 at 00:54
  • 1
    @KorsaR - naming something "buggy" just because it follows public specification may be overkill. Consider reading about Xml namespaces... – Alexei Levenkov Sep 10 '13 at 01:02
  • 1
    If it works, go for it, XDocument works well with Linq but if you don't need or prefer to do Linq queries against the loaded Xml just use System.Xml.Document instead. It is possible that it is some kind of bug that System.Xml.Document correctly parses the xml into its parent and child nodes but XDocument does not. But again if you don't have a need to query the loaded Xml with Linq then just go with what works until requirements change. – Brian Ogden Sep 10 '13 at 02:30
1

You have to use proper XNamespace instance when querying this document. That's because your <connections> tag sets the default namespace to "http://schemas.openxmlformats.org/spreadsheetml/2006/main".

var xDoc = XDocument.Load("Input.txt");
var ns = XNamespace.Get("http://schemas.openxmlformats.org/spreadsheetml/2006/main");

var odcFile = xDoc.Root.Elements(ns + "connection")
                       .FirstOrDefault(x => (int)x.Attribute("id") == 1)
                       .Attribute("odcFile");

odcFile.Value = "newOdcValue";

xDoc.Save("Input.txt");
MarcinJuraszek
  • 124,003
  • 15
  • 196
  • 263