name() function fails in MSXML
-
I have tried an XPath successfully in both XML Spy, and SketchPath, but I cannot make it work in MSXML The XPath without the name() function works fine in MSXML, but as soon as I try and use name() it fails. I have setup a prefix using SelectionNamespaces, of find I want to find the name of the first element attached to DesiredNode. I originally tried name(//parent:node()/find:DesiredNode/node()) which failed, I then tried //parent:node()/find:DesiredNode/node() , this however works fine I have also tried alternate XPaths such as name(//find:DesiredNode/*), but this fails also. All XML Spy XPath work (without the need for using the find prefix), and if I setup the alias of find correctly in SketchPath, I also always get the correct results. What am I doing wrong?
-
I have tried an XPath successfully in both XML Spy, and SketchPath, but I cannot make it work in MSXML The XPath without the name() function works fine in MSXML, but as soon as I try and use name() it fails. I have setup a prefix using SelectionNamespaces, of find I want to find the name of the first element attached to DesiredNode. I originally tried name(//parent:node()/find:DesiredNode/node()) which failed, I then tried //parent:node()/find:DesiredNode/node() , this however works fine I have also tried alternate XPaths such as name(//find:DesiredNode/*), but this fails also. All XML Spy XPath work (without the need for using the find prefix), and if I setup the alias of find correctly in SketchPath, I also always get the correct results. What am I doing wrong?
-
Are you setting the SelectionLanguage property? See this thread below.[^]
led mike
Yes I am, I've also used the SelectionNamespaces property to setup a namespace alias. This works fine as long as I don't introduce name()
-
Yes I am, I've also used the SelectionNamespaces property to setup a namespace alias. This works fine as long as I don't introduce name()
-
Post the following: * MSXML version you are using * Code setting SelectionLanguage * Code setting SelectionNamespaces * XPath statements that fail * Smallest possible XML representing the problem.
led mike
> Post the following: > > * MSXML version you are using Tried both 3 and 6 > * Smallest possible XML representing the problem.
<responseenv xmlns="http://example" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" schemaversion="3.0">
<header schemaversion="1.1">
<field1/>
</header>
<bodies>
<response>
<field1/>
</response>
</bodies>
</responseenv>* Code setting SelectionLanguage
HRESULT hr = domDoc->setProperty(_bstr_t("SelectionLanguage"),_variant_t(_bstr_t("XPath")));
> * Code setting SelectionNamespaceshr = domDoc->setProperty(_bstr_t("SelectionNamespaces"),_variant_t(_bstr_t("xmlns:find=\"http://example\"")));
> * XPath statements that failname(/find:ResponseEnv/find:Bodies/node()) name(//find:Bodies/node())
* Code in FullMSXML::IXMLDOMDocument2Ptr domDoc(__uuidof(MSXML2::DOMDocument60));
if ( domDoc->loadXML(sExample.c_str()) == VARIANT_TRUE)
{
HRESULT hr = domDoc->setProperty(_bstr_t("SelectionLanguage"),_variant_t(_bstr_t("XPath")));
if (FAILED(hr))
return 1;
hr = domDoc->setProperty(_bstr_t("SelectionNamespaces"),_variant_t(_bstr_t("xmlns:find=\"http://example\"")));
if (FAILED(hr))
return 1;
MSXML::IXMLDOMElementPtr pElem = NULL;
try
{
//pElem = domDoc->selectSingleNode(_bstr_t("/find:ResponseEnv/find:Bodies/node()"));//Works
pElem = domDoc->selectSingleNode(_bstr_t("name(/find:ResponseEnv/find:Bodies/node())"));
}
catch (const _com_error &e)
{
MessageBox(NULL, static_cast<LPCTSTR>(e.Description()), e.ErrorMessage(), MB_OK);
}
}The original code was using an internal C+++ wrapper hiding the specifics of calling MSXML code, and was using raw_interfaces_only and so did not throw. The example above returns the error text "Expression must evaluate to a node-set", the original company code modified to throw a _com_error, returns a slightly different message "Expression does not return a DOM node.". Peter
-
> Post the following: > > * MSXML version you are using Tried both 3 and 6 > * Smallest possible XML representing the problem.
<responseenv xmlns="http://example" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" schemaversion="3.0">
<header schemaversion="1.1">
<field1/>
</header>
<bodies>
<response>
<field1/>
</response>
</bodies>
</responseenv>* Code setting SelectionLanguage
HRESULT hr = domDoc->setProperty(_bstr_t("SelectionLanguage"),_variant_t(_bstr_t("XPath")));
> * Code setting SelectionNamespaceshr = domDoc->setProperty(_bstr_t("SelectionNamespaces"),_variant_t(_bstr_t("xmlns:find=\"http://example\"")));
> * XPath statements that failname(/find:ResponseEnv/find:Bodies/node()) name(//find:Bodies/node())
* Code in FullMSXML::IXMLDOMDocument2Ptr domDoc(__uuidof(MSXML2::DOMDocument60));
if ( domDoc->loadXML(sExample.c_str()) == VARIANT_TRUE)
{
HRESULT hr = domDoc->setProperty(_bstr_t("SelectionLanguage"),_variant_t(_bstr_t("XPath")));
if (FAILED(hr))
return 1;
hr = domDoc->setProperty(_bstr_t("SelectionNamespaces"),_variant_t(_bstr_t("xmlns:find=\"http://example\"")));
if (FAILED(hr))
return 1;
MSXML::IXMLDOMElementPtr pElem = NULL;
try
{
//pElem = domDoc->selectSingleNode(_bstr_t("/find:ResponseEnv/find:Bodies/node()"));//Works
pElem = domDoc->selectSingleNode(_bstr_t("name(/find:ResponseEnv/find:Bodies/node())"));
}
catch (const _com_error &e)
{
MessageBox(NULL, static_cast<LPCTSTR>(e.Description()), e.ErrorMessage(), MB_OK);
}
}The original code was using an internal C+++ wrapper hiding the specifics of calling MSXML code, and was using raw_interfaces_only and so did not throw. The example above returns the error text "Expression must evaluate to a node-set", the original company code modified to throw a _com_error, returns a slightly different message "Expression does not return a DOM node.". Peter
Stone Free wrote:
name(/find:ResponseEnv/find:Bodies/node())
I have never seen
name()
used like that and I have no idea what this "find:
" is nor can I find it referenced on www.w3schools.com. If that is newer XPath then of course it's not going to be supported in old DOMs like MSXML. To output a node name I would have have an XSLT like<for-each select="/Bodies">
<value-of select="name()"/>
</for-each>I don't know if you are using the XPath statement in XSLT or not but name() returns a string not a node which is why the error message says what it says. After seeing your XPath statements I don't have clue what you are trying to do.
led mike
-
Stone Free wrote:
name(/find:ResponseEnv/find:Bodies/node())
I have never seen
name()
used like that and I have no idea what this "find:
" is nor can I find it referenced on www.w3schools.com. If that is newer XPath then of course it's not going to be supported in old DOMs like MSXML. To output a node name I would have have an XSLT like<for-each select="/Bodies">
<value-of select="name()"/>
</for-each>I don't know if you are using the XPath statement in XSLT or not but name() returns a string not a node which is why the error message says what it says. After seeing your XPath statements I don't have clue what you are trying to do.
led mike
Stone Free wrote:
name(/find:ResponseEnv/find:Bodies/node())
led mike wrote:
I have never seen name() used like that and I have no idea what this "find:" is nor can I find it referenced on www.w3schools.com. If that is newer XPath then of course it's not going to be supported in old DOMs like MSXML.
Mike, find: won't be referenced at www.w3schools.com, because it is a namespace alias. Take
/ResponseEnv/Bodies/node()
for example, this would work fine if my XML had been as follows:<responseenv>
<header schemaversion="1.1">
<field1/>
</header>
<bodies>
<response>
<field1/>
</response>
</bodies>
</responseenv>Unfortunately it has a namespace attached to it of http://example. To make the XPath work successfully I had to use the SelectionNamespaces property. I could have made the alias anything. I could have written the following:
hr = domDoc->setProperty(_bstr_t("SelectionNamespaces"),_variant_t(_bstr_t("xmlns:codeproject=\"http://example\"")));
This would mean my XPath would have been/codeproject:ResponseEnv/codeproject:Bodies/node()
led mike wrote:
I have never seen name() used like that
I got that syntax:
- name(): Returns the qualified name of the context node.
- name(node_set): Returns the qualified name of the first node in the given node set object.
From http://www.herongyang.com/xml/xpath_2.html[^]
led mike wrote:
I don't know if you are using the XPath statement in XSLT or not but name() returns a string not a node which is why the error message says what it says. After seeing your XPath statements I don't have clue what you are trying to do.
No the XPath statement is being used directly from the XML Document. The node identified with will not actually be called response, but can be a number of different sub-messages and so I don't know in advance what it will be only that it will be the first node found that is a child of bodies
-
> Post the following: > > * MSXML version you are using Tried both 3 and 6 > * Smallest possible XML representing the problem.
<responseenv xmlns="http://example" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" schemaversion="3.0">
<header schemaversion="1.1">
<field1/>
</header>
<bodies>
<response>
<field1/>
</response>
</bodies>
</responseenv>* Code setting SelectionLanguage
HRESULT hr = domDoc->setProperty(_bstr_t("SelectionLanguage"),_variant_t(_bstr_t("XPath")));
> * Code setting SelectionNamespaceshr = domDoc->setProperty(_bstr_t("SelectionNamespaces"),_variant_t(_bstr_t("xmlns:find=\"http://example\"")));
> * XPath statements that failname(/find:ResponseEnv/find:Bodies/node()) name(//find:Bodies/node())
* Code in FullMSXML::IXMLDOMDocument2Ptr domDoc(__uuidof(MSXML2::DOMDocument60));
if ( domDoc->loadXML(sExample.c_str()) == VARIANT_TRUE)
{
HRESULT hr = domDoc->setProperty(_bstr_t("SelectionLanguage"),_variant_t(_bstr_t("XPath")));
if (FAILED(hr))
return 1;
hr = domDoc->setProperty(_bstr_t("SelectionNamespaces"),_variant_t(_bstr_t("xmlns:find=\"http://example\"")));
if (FAILED(hr))
return 1;
MSXML::IXMLDOMElementPtr pElem = NULL;
try
{
//pElem = domDoc->selectSingleNode(_bstr_t("/find:ResponseEnv/find:Bodies/node()"));//Works
pElem = domDoc->selectSingleNode(_bstr_t("name(/find:ResponseEnv/find:Bodies/node())"));
}
catch (const _com_error &e)
{
MessageBox(NULL, static_cast<LPCTSTR>(e.Description()), e.ErrorMessage(), MB_OK);
}
}The original code was using an internal C+++ wrapper hiding the specifics of calling MSXML code, and was using raw_interfaces_only and so did not throw. The example above returns the error text "Expression must evaluate to a node-set", the original company code modified to throw a _com_error, returns a slightly different message "Expression does not return a DOM node.". Peter
The XPath "name" function returns a string and not a node-set. Thus "
pElem = domDoc->selectSingleNode(_bstr_t("name(/find:ResponseEnv/find:Bodies/node())"));
" won't work. I believe "IXMLDOMElement" has a "nodeName" property that returns what you are looking for."We make a living by what we get, we make a life by what we give." --Winston Churchill
-
Stone Free wrote:
name(/find:ResponseEnv/find:Bodies/node())
led mike wrote:
I have never seen name() used like that and I have no idea what this "find:" is nor can I find it referenced on www.w3schools.com. If that is newer XPath then of course it's not going to be supported in old DOMs like MSXML.
Mike, find: won't be referenced at www.w3schools.com, because it is a namespace alias. Take
/ResponseEnv/Bodies/node()
for example, this would work fine if my XML had been as follows:<responseenv>
<header schemaversion="1.1">
<field1/>
</header>
<bodies>
<response>
<field1/>
</response>
</bodies>
</responseenv>Unfortunately it has a namespace attached to it of http://example. To make the XPath work successfully I had to use the SelectionNamespaces property. I could have made the alias anything. I could have written the following:
hr = domDoc->setProperty(_bstr_t("SelectionNamespaces"),_variant_t(_bstr_t("xmlns:codeproject=\"http://example\"")));
This would mean my XPath would have been/codeproject:ResponseEnv/codeproject:Bodies/node()
led mike wrote:
I have never seen name() used like that
I got that syntax:
- name(): Returns the qualified name of the context node.
- name(node_set): Returns the qualified name of the first node in the given node set object.
From http://www.herongyang.com/xml/xpath_2.html[^]
led mike wrote:
I don't know if you are using the XPath statement in XSLT or not but name() returns a string not a node which is why the error message says what it says. After seeing your XPath statements I don't have clue what you are trying to do.
No the XPath statement is being used directly from the XML Document. The node identified with will not actually be called response, but can be a number of different sub-messages and so I don't know in advance what it will be only that it will be the first node found that is a child of bodies
Stone Free wrote:
No the XPath statement is being used directly from the XML Document.
Do you have any experience using a DOM with
selectSingleNode
()? As far as I know you can't return the result ofname()
as a node because it's not a node. Therefore what you are trying to do below makes no sense to me.pElem = domDoc->selectSingleNode(_bstr_t("name(/find:ResponseEnv/find:Bodies/node())"));
led mike