19

I am receiving 'xsi' is an undeclared prefix using XmlDocument.

I am trying to read a file which has the following schema:

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2"
     xmlns:gx="http://www.google.com/kml/ext/2.2" 
     xmlns:kml="http://www.opengis.net/kml/2.2"
     xmlns:atom="http://www.w3.org/2005/Atom">
        <Document>
            <Document id="robert" xsi:schemaLocation="http://www.opengis.net/kml/2.2 http://schemas.opengis.net/kml/2.2.0/ogckml22.xsd http://www.google.com/kml/ext/2.2 http://code.google.com/apis/kml/schema/kml22gx.xsd">
              <Placemark>
                <description>test</description>
              </Placemark>
        </Document>
    </Document>
</kml>

I have tried the following:

    XmlDocument xmldoc = new XmlDocument();
    using (XmlTextReader tr = new XmlTextReader(strXmlFile))
    {
        //tr.Namespaces = false; (uncomment to ignore namespace)
        xmldoc.Load(tr);  // 'xsi' is an undeclared prefix error here
    }

If I uncomment the line to ignore the namespace, it loads ok but fails to save the XmlDocument later on. So ignoring it would not be a solution. Does anyone know how to properly load the schema? The issue/error appears to be in this node:

<Document id="robert" xsi:schemaLocation="http://www.opengis.net/kml/2.2 http://schemas.opengis.net/kml/2.2.0/ogckml22.xsd http://www.google.com/kml/ext/2.2 http://code.google.com/apis/kml/schema/kml22gx.xsd">

Update #1 I tried the following:

XmlDocument xmldoc = new XmlDocument();
NameTable nt = new NameTable();
XmlNamespaceManager nsmgr = new XmlNamespaceManager(nt);
nsmgr.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
XmlParserContext context = new XmlParserContext(null, nsmgr, null, XmlSpace.None);
XmlReaderSettings xset = new XmlReaderSettings();
xset.ConformanceLevel = ConformanceLevel.Fragment;
XmlReader rd = XmlReader.Create(new StringReader(strXmlFile), xset, context);
xmldoc.Load(rd);  // error is still on this line

But am receiving this error now:

"The specified node cannot be inserted as the valid child of this node, because the specified node is the wrong type." It looks like I am getting closer...

user3062349
  • 691
  • 2
  • 7
  • 15

2 Answers2

21

Solution:

I was able to solve the problem! Here is the final code:

XmlDocument xmldoc = new XmlDocument();
XmlReaderSettings settings = new XmlReaderSettings { NameTable = new NameTable() };
XmlNamespaceManager xmlns = new XmlNamespaceManager(settings.NameTable);
xmlns.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
XmlParserContext context = new XmlParserContext(null, xmlns, "", XmlSpace.Default);
XmlReader reader = XmlReader.Create(strXmlFile, settings, context);
xmldoc.Load(reader);

Also one more tip, when searching through the nodes, remember to set the correct namespace, for example to search for Placemark above, this would be the format:

// Setup default namespace manager for searching through nodes
XmlNamespaceManager manager = new XmlNamespaceManager(xmldoc.NameTable);
string defaultns = xmldoc.DocumentElement.GetNamespaceOfPrefix("");
manager.AddNamespace("ns", defaultns);

// get a list of all <Placemark> nodes
XmlNodeList listOfPlacemark = xmldoc.SelectNodes("//ns:Placemark", manager);

// iterate over the <Placemark> nodes
foreach (XmlNode singlePlaceMark in listOfPlacemark)

// Get the description subnode
XmlNode descriptionNode = singlePlaceMark.SelectSingleNode("ns:description", manager);

..
user3062349
  • 691
  • 2
  • 7
  • 15
16

You are missing the xsinamespace declaration:

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

now your document should look something like this:

<kml xmlns="http://www.opengis.net/kml/2.2"
          xmlns:gx="http://www.google.com/kml/ext/2.2" 
          xmlns:kml="http://www.opengis.net/kml/2.2"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns:atom="http://www.w3.org/2005/Atom">
.....
</kml>
Mario Stoilov
  • 3,411
  • 5
  • 31
  • 51
  • 2
    Thanks for your prompt response. One question, how would you do that before the xmldoc.load (in the source code) since I cannot change the original file itself. Thanks again. – user3062349 Dec 17 '13 at 15:34
  • If the file is missing it, then it is an invalid xml file(you cannot use an undeclared namespace) and needs to be fixed. From where are you getting these files – Mario Stoilov Dec 17 '13 at 15:37
  • The file is a valid google earth KML file in XML format. It does open up correctly in Google earth. – user3062349 Dec 17 '13 at 15:42
  • take a look here then - http://msdn.microsoft.com/en-us/library/system.xml.xmlnamespacemanager.addnamespace%28v=vs.110%29.aspx and see if it works for you – Mario Stoilov Dec 17 '13 at 15:46
  • Thank you again Mario. As you suggested, I tried the code and I am getting closer to solving it but still have some tweaking to do... (See update #1) – user3062349 Dec 17 '13 at 15:55