简体   繁体   English

查询XmlDocument而不会得到“未定义名称空间前缀”问题

[英]Query an XmlDocument without getting a 'Namespace prefix is not defined' problem

I've got an Xml document that both defines and references some namespaces. 我有一个Xml文档,它定义和引用一些命名空间。 I load it into an XmlDocument object and to the best of my knowledge I create a XmlNamespaceManager object with which to query Xpath against. 我将它加载到XmlDocument对象中,据我所知,我创建了一个XmlNamespaceManager对象,用它来查询Xpath。 Problem is I'm getting XPath exceptions that the namespace "my" is not defined. 问题是我得到了XPath异常,命名空间“my”没有定义。 How do I get the namespace manager to see that the namespaces I am referencing are already defined. 如何让命名空间管理器看到我引用的命名空间已经定义。 Or rather how do I get the namespace definitions from the document to the namespace manager. 或者更确切地说,如何从文档到命名空间管理器获取命名空间定义。

Furthermore tt strikes me as strange that you have to provide a namespace manager to the document which you create from the documents nametable in the first place. 此外tt让我感到奇怪的是,您必须首先为文档名称表创建的文档提供命名空间管理器。 Even if you need to hardcode manual namespaces why can't you add them directly to the document. 即使您需要对手动命名空间进行硬编码,为什么不能将它们直接添加到文档中。 Why do you always have to pass this namespace manager with every single query? 为什么总是必须在每个查询中传递此命名空间管理器? What can't XmlDocument just know? 什么不能XmlDocument只知道?

Code: 码:

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:

  <?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> 

Update: 更新:

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");

This does the job, but it mean's I have to hard code to this particular xml schema. 这样做,但这意味着我必须硬编码到这个特定的xml架构。 This schema represents an infopath form template. 此架构表示infopath表单模板。 In particular the my namespace url will be different for every form template so I really don't want to hardcode this. 特别是我的命名空间url对于每个表单模板都是不同的,所以我真的不想硬编码。 It would be nice to find a clean way to get this namespace from the xml without resorting to RegEx. 很高兴找到一种从xml获取此命名空间的简洁方法,而无需使用RegEx。

I was hoping that the XmlNamespaceManager would just sort of pick up the namespace definitions form the NameTable. 我希望XmlNamespaceManager只是从NameTable中获取命名空间定义。 I mean their in the Xml but I still have to define them. 我的意思是他们在Xml中,但我仍然需要定义它们。

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");

This does the job, but it mean's I have to hard code to this particular xml schema. 这样做,但这意味着我必须硬编码到这个特定的xml架构。 This schema represents an infopath form template. 此架构表示infopath表单模板。 In particular the my namespace url will be different for every form template so I really don't want to hardcode this. 特别是我的命名空间url对于每个表单模板都是不同的,所以我真的不想硬编码。 It would be nice to find a clean way to get this namespace from the xml without resorting to Regex. 很高兴找到一种干净的方法从xml获取这个命名空间而不需要使用Regex。

I was hoping that the XmlNamespaceManager would just sort of pick up the namespace definitions form the NameTable. 我希望XmlNamespaceManager只是从NameTable中获取命名空间定义。 I mean their in the Xml but I still have to define them. 我的意思是他们在Xml中,但我仍然需要定义它们。

Here is the answer to the "What can't XmlDocument just know?" 这是“什么不能XmlDocument只知道?”的答案。 question. 题。

NameTable is just an optimization for storing names. NameTable只是存储名称的优化。 It has actually nothing to do with namespaces. 它实际上与名称空间无关。

And even if XmlNamespaceManager could infer all namespaces and prefixes from XML doc that won't help in general case because of XML namespaces nature, eg what would XmlNamespaceManager map "my" prefix in this case: 即使XmlNamespaceManager可以推断出XML文档中的所有命名空间和前缀,由于XML命名空间的性质,在一般情况下也无济于事,例如XmlNamespaceManager在这种情况下会映射“my”前缀:

<root>
    <foo xmlns:my="blah"/>
    <foo xmlns:my="balh-blah-blah"/>
</root>

Have you defined "my" in the namespace-manager? 你在命名空间管理器中定义了“我的”吗?

ns.AddNamespace("my", "http://schemas.microsoft.com/office/infopath/2003/myXSD/2010-01-15T18:21:55");

Or better - choose something that is unlikely to conflict. 或者更好 - 选择不太可能发生冲突的事情。 It does seem odd that it didn't pick it up from the name-table, though. 不过,它似乎很奇怪它没有从名称表中提取它。

For me with InfoPath 2007 this solved the problem 对于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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM