Kristian Nissen
Kristian Nissen

Reputation: 1184

Xpath cannot parse XML : Namespace manager or XsltContext needed

I wish to find the element

r with s:id = {5FF71EB5-BE2D-49DC-9442-B3DCE15067C9}

and its <rule> with the

uid="{00000000-0000-0000-0000-000000000000}" 

and then in the end output the value of s:name ("Bar1")

i have written this piece of xpath, that does exactly that.

string(//r[@s:id='{5FF71EB5-BE2D-49DC-9442-B3DCE15067C9}']//rule[@uid='{00000000:0000:0000:0000:000000000000}']/@s:name)

Validated at: http://codebeautify.org/Xpath-Tester

<r xmlns:p="p" xmlns:s="s" p:p="1">
    <d>
        <r s:id="{5FF71EB5-BE2D-49DC-9442-B3DCE15067C9}" > -- this one
            <rls>
                <ruleset>
                    <rule uid="{6D78B8A0-4A3D-4B73-8282-2954047089C6}" s:name="Foo">
                    </rule>
                    <rule uid="{35255912-743A-4CBC-909E-9DA3BBFD0F36}" s:name="FooBar">

                    </rule>
                    <rule uid="{A1FF1DD0-8D2E-4F1A-94D1-665B1F4E2074}" s:name="Foo1">

                    </rule>
                    <rule uid="{00000000-0000-0000-0000-000000000000}" s:name="Bar1"> --
                    </rule>
                </ruleset>
            </rls>
        </r>
        <r uid="{864C965D-42D8-426F-9A94-BAEA11EA1CCA}">
            <rls>
                <ruleset>
                    <rule uid="{8C215312-B610-4A10-9DC7-E3FE226D948B}" s:name="Fooo">
                    </rule>
                    <rule uid="{00000000-0000-0000-0000-000000000000}" s:name="Baar">
                    </rule>
                </ruleset>
            </rls>
        </r>
    </d>
</r>

The way i execute the Xpath is like this:

var xmlStringReader = new StringReader(xmlfile);

XmlReaderSettings set = new XmlReaderSettings();
set.ConformanceLevel = ConformanceLevel.Fragment;

XPathDocument doc =
    new XPathDocument(XmlReader.Create(xmlStringReader, set));

XPathNavigator nav = doc.CreateNavigator();
var xmlnsManager = new XmlNamespaceManager(nav.NameTable);

xmlnsManager.AddNamespace("p", "p" );
xmlnsManager.AddNamespace("s", "s" );

var xpath ="r[@s:id='{5FF71EB5-BE2D-49DC-9442-B3DCE15067C9}']//rule[@uid='{00000000-0000-0000-0000-000000000000}']";
string result = nav.SelectSingleNode(xpath).Value;

My error is: Namespace Manager or XsltContext needed. This query has a prefix, variable, or user-defined function.

I have through a lot of digging around figured that my namespaces are not properly set. But i cannot for the life of me figure out, what i am doing wrong.

How are my namespace assignments supposed to look like?

Upvotes: 1

Views: 628

Answers (1)

Volkan Paksoy
Volkan Paksoy

Reputation: 6957

You have to provide the namespace manager to the navigator. That takes care of the exception but SelectSingleNode was returning null. So I changed the XPath (prepended // to search all nodes). This finds the node but Value property is empty string so I changed it to OuterXml. My final version is as below:

var xpath = "//r[@s:id='{5FF71EB5-BE2D-49DC-9442-B3DCE15067C9}']//rule[@uid='{00000000-0000-0000-0000-000000000000}']";
var result = nav.SelectSingleNode(xpath, xmlnsManager);
Console.WriteLine(result.OuterXml);
// Prints: "<rule uid=\"{00000000-0000-0000-0000-000000000000}\" s:name=\"Bar1\" xmlns:s=\"s\"></rule>"

Upvotes: 2

Related Questions