题
什么是背后的故事XPath和支持的名字空间?有没有XPath作为一个说明书之前命名空间?如果我有一个文件里的元素已经被给予一个默认的名字空间:
<foo xmlns="uri" />
它的出现,虽然一些XPath处理图书馆不会承认 //foo
因为空间,而其他人会。选择我的团队已经想过是添加一个名字空间的前缀使用经常表达的XPath(你可以增添一个名字空间的前缀通过XmlNameTable)但是,这似乎脆因为XPath是这样一个灵活的语言,当它涉及到节点试验。
是否有一个标准适用于这个?
我的方法是一位予以解决了,但它似乎工作罚款;我删除了 xmlns
《宣言》有一个搜索/替换,然后应用XPath。
string readyForXpath = Regex.Replace(xmldocument, "xmlns=\".+\"", String.Empty );
那是一个公平的做法或具有任何解决此不同?
解决方案
我尝试过类似的东西palehorse建议和可能未得到它的工作。因为我得到的数据出版服务,我不能改变xml。我最终使用如下和XmlNamespaceManager像这样:
XmlDocument doc = new XmlDocument();
doc.LoadXml(xmlWithBogusNamespace);
XmlNamespaceManager nSpace = new XmlNamespaceManager(doc.NameTable);
nSpace.AddNamespace("myNs", "http://theirUri");
XmlNodeList nodes = doc.SelectNodes("//myNs:NodesIWant",nSpace);
//etc
其他提示
你需要的当地名称():
http://www.w3.org/TR/xpath#function-local-name
为从婴儿床 http://jcooney.net/archive/2005/08/09/6517.aspx:
<foo xmlns='urn:foo'>
<bar>
<asdf/>
</bar>
</foo>
这种表达将匹配"条"的元素:
//*[local-name()='bar']
这个不会:
//bar
问题是,一个元素没有一个名字空间被宣布为在空namespace-因此,如果//foo相匹配的名字空间,你认为是"默认"将会有没有办法参考中的一个元素null名字空间。
记得,前一个名字空间仅仅是一个简写《公约》,真实的元素名称(有资格的名称,或QName为短期)组成的全名字空间和地名。改变的前一个名字空间不会改变的"身份"的元素--如果在同一个名字空间和同一地方名称,然后它是相同种类的元素,即使该前缀是不同的。
XPath2.0(或者说XSLT2.0)已经概念的'默认的xpath namespace'.你可以设定xpath-default-名字空间属性xsl:样式表件。
如果你试图使用xslt你可以添加的空间来的样式表宣言》。如果你这么做,则必须确保有一个前缀或者它不会的工作。如果来源XML没有前缀,这仍然是好的,你添加自己的前缀在的样式表。
样式
<xsl:stylesheet
xmlns:fb="uri"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="fb:foo/bar">
<!-- do stuff here -->
</xsl:template>
</xsl:stylsheet>
或者类似的东西。
使用用于看来这个工作:
http://xmlsoft.org/examples/xpath1.c
int
register_namespaces(xmlXPathContextPtr xpathCtx, const xmlChar* nsList) {
xmlChar* nsListDup;
xmlChar* prefix;
xmlChar* href;
xmlChar* next;
assert(xpathCtx);
assert(nsList);
nsListDup = xmlStrdup(nsList);
if(nsListDup == NULL) {
fprintf(stderr, "Error: unable to strdup namespaces list\n");
return(-1);
}
next = nsListDup;
while(next != NULL) {
/* skip spaces */
while((*next) == ' ') next++;
if((*next) == '\0') break;
/* find prefix */
prefix = next;
next = (xmlChar*)xmlStrchr(next, '=');
if(next == NULL) {
fprintf(stderr,"Error: invalid namespaces list format\n");
xmlFree(nsListDup);
return(-1);
}
*(next++) = '\0';
/* find href */
href = next;
next = (xmlChar*)xmlStrchr(next, ' ');
if(next != NULL) {
*(next++) = '\0';
}
/* do register namespace */
if(xmlXPathRegisterNs(xpathCtx, prefix, href) != 0) {
fprintf(stderr,"Error: unable to register NS with prefix=\"%s\" and href=\"%s\"\n", prefix, href);
xmlFree(nsListDup);
return(-1);
}
}
xmlFree(nsListDup);
return(0);
}