在不出现“命名空间前缀未定义”的问题的情况下查询XmlDocument

11
我有一个Xml文档,其中定义并引用了一些命名空间。我将其加载到XmlDocument对象中,并创建了一个XmlNamespaceManager对象进行Xpath查询,但是我得到了XPath异常,显示命名空间“my”未定义。如何让命名空间管理器看到我正在引用的命名空间已经被定义。或者说,如何将文档中的命名空间定义添加到命名空间管理器中。
此外,让我感到奇怪的是,你必须向你从文档的名称表创建的文档提供一个命名空间管理器。即使你需要硬编码手动设置命名空间,为什么不能直接将它们添加到文档中。为什么每次查询都必须传递这个命名空间管理器? XmlDocument不能自己知道吗?
代码:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(programFiles + @"Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\FEATURES\HfscBookingWorkflow\template.xml");
XmlNamespaceManager ns = new XmlNamespaceManager(xmlDoc.NameTable);

XmlNode referenceNode = xmlDoc.SelectSingleNode("/my:myFields/my:ReferenceNumber", ns);
referenceNode.InnerXml = this.bookingData.ReferenceNumber;

XmlNode titleNode = xmlDoc.SelectSingleNode("/my:myFields/my:Title", ns);
titleNode.InnerXml = this.bookingData.FamilyName;

Xml:

  <?xml version="1.0" encoding="UTF-8" ?> 
  <?mso-infoPathSolution name="urn:schemas-microsoft-com:office:infopath:Inspection:-myXSD-2010-01-15T18-21-55" solutionVersion="1.0.0.104" productVersion="12.0.0" PIVersion="1.0.0.0" ?> 
  <?mso-application progid="InfoPath.Document" versionProgid="InfoPath.Document.2"?> 
  <my:myFields xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2010-01-15T18:21:55" xmlns:xd="http://schemas.microsoft.com/office/infopath/2003">
  <my:DateRequested xsi:nil="true" /> 
  <my:DateVisited xsi:nil="true" /> 
  <my:ReferenceNumber /> 
  <my:FireCall>false</my:FireCall> 

更新:

ns.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
ns.AddNamespace("xhtml", "http://www.w3.org/1999/xhtml");
ns.AddNamespace("xd", "http://schemas.microsoft.com/office/infopath/2003");
ns.AddNamespace("my", "http://schemas.microsoft.com/office/infopath/2003/myXSD/2010-01-15T18:21:55");
这个代码可以完成任务,但这意味着我必须硬编码到这个特定的XML模式中。 这个模式代表一个InfoPath表单模板。 特别是每个表单模板的my namespace url都将不同,所以我真的不想硬编码它。 希望找到一种干净的方法来从XML中获取这个命名空间,而不用使用正则表达式。
我希望XmlNamespaceManager会从NameTable中自动获取命名空间定义。 我的意思是它们在XML中,但我仍然需要定义它们。
4个回答

5
ns.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
ns.AddNamespace("xhtml", "http://www.w3.org/1999/xhtml");
ns.AddNamespace("xd", "http://schemas.microsoft.com/office/infopath/2003");
ns.AddNamespace("my", "http://schemas.microsoft.com/office/infopath/2003/myXSD/2010-01-15T18:21:55");

这段代码可以完成任务,但是它意味着我必须硬编码到特定的xml模式中。这个模式表示一个infopath表单模板。特别地,每个表单模板的my命名空间url都不同,因此我真的不想硬编码它。找到一种干净的方法从xml中获取这个命名空间而不是使用正则表达式会很好。
我希望XmlNamespaceManager可以从NameTable中自动获取命名空间定义。我的意思是,它们在Xml中,但我仍然需要定义它们。

3
以下是关于“What can't XmlDocument just know?”问题的答案:
NameTable仅仅是一种存储名称的优化方式,与命名空间实际上没有任何关系。
即使XmlNamespaceManager可以从XML文档中推断出所有命名空间和前缀,在一般情况下也无法帮助解决XML命名空间的本质问题。例如,在以下情况下,XmlNamespaceManager将如何映射“my”前缀:
<root>
    <foo xmlns:my="blah"/>
    <foo xmlns:my="balh-blah-blah"/>
</root>

1
你在命名空间管理器中定义了“my”吗?
ns.AddNamespace("my", "http://schemas.microsoft.com/office/infopath/2003/myXSD/2010-01-15T18:21:55");

或者更好的选择是选择一些不太可能发生冲突的内容。不过,它似乎没有从名称表中获取到这个信息,这有点奇怪。

1
NameTable只是一种存储名称的优化方式,与命名空间实际上没有任何关系。即使XmlNamespaceManager可以从XML文档中推断出所有命名空间和前缀,在一般情况下也无法解决XML命名空间的本质问题。例如,在此情况下,XmlNamespaceManager将如何映射“my”前缀: <root> <foo xmlns:my="blah"/> <foo xmlns:my="balh-blah-blah"/> </root> - Oleg Tkachenko
@Oleg - 我认为你应该保留你的答案(而不是删除它)- 这是一个很好的回答“为什么?”的问题。 - Marc Gravell
我没有手动添加它,因为命名空间的URL可能会更改。我尝试使用XPath获取的字段不会更改。 - Daniel Revell

0

对于我来说,使用InfoPath 2007解决了这个问题。

static public XmlNamespaceManager GetNameSpaceManager(this XmlDocument document)
{
    XmlNamespaceManager xmlNamespaceManager = new XmlNamespaceManager(document.NameTable);

    xmlNamespaceManager.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
    xmlNamespaceManager.AddNamespace("dfs", "http://schemas.microsoft.com/office/infopath/2003/dataFormSolution");
    xmlNamespaceManager.AddNamespace("d", "http://schemas.microsoft.com/office/infopath/2003/ado/dataFields");
    xmlNamespaceManager.AddNamespace("my", "http://schemas.microsoft.com/office/infopath/2003/myXSD/2012-03-29T06:28:28");
    xmlNamespaceManager.AddNamespace("xd", "http://schemas.microsoft.com/office/infopath/2003");

    return xmlNamespaceManager;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接