C# 使用XmlDocument从具有或不具有命名空间的xml文件中读取
我有一些代码使用XmlDocument从具有名称空间的xml文件读取。我的挑战是,我现在读取的文件名称空间是硬编码的,我将其传递给XmlNamespaceManager。我希望我的方法更加灵活。从任何类型的xml文件读取。如果它具有名称空间,然后使用名称空间管理器读取元素,而无需对名称空间进行硬编码。如果文件没有名称空间,则继续分析它。下面是我所做的C# 使用XmlDocument从具有或不具有命名空间的xml文件中读取,c#,xml,namespaces,C#,Xml,Namespaces,我有一些代码使用XmlDocument从具有名称空间的xml文件读取。我的挑战是,我现在读取的文件名称空间是硬编码的,我将其传递给XmlNamespaceManager。我希望我的方法更加灵活。从任何类型的xml文件读取。如果它具有名称空间,然后使用名称空间管理器读取元素,而无需对名称空间进行硬编码。如果文件没有名称空间,则继续分析它。下面是我所做的 xmldoc = new XmlDocument (); xmldoc.Load (fileLocation); XmlNamespaceMa
xmldoc = new XmlDocument ();
xmldoc.Load (fileLocation);
XmlNamespaceManager nameSpaceManager = new XmlNamespaceManager(xmldoc.NameTable);
nameSpaceManager.AddNamespace ("ns","http://schemas.sample.data.org/2005");
XmlNodeList nodeList = xmldoc.SelectNodes("/ns:Demo/ns:Items", nameSpaceManager);
if (nodeList != null)
{
foreach (XmlNode childNode in nodeList)
{
string first = childNode.SelectSingleNode ("ns:First", nameSpaceManager).InnerText;
string second= childNode.SelectSingleNode ("ns:Second", nameSpaceManager).InnerText;
string third = childNode.SelectSingleNode ("ns:Third", nameSpaceManager).InnerText;
}
}
下面是我正在使用的示例xml文件
<Demo xmlns:i="http://www.justasample.com" xmlns="http://schemas.sample.data.org/2005">
<Items>
<First>first</First>
<Second>second</Second>
<Third>third</Third>
</Items>
</Demo>
第一
第二
第三
使用Linq to XML和my,特别是内部处理的,您可以执行以下操作:
XElement root = XElement.Load(fileLocation);
var items = root.Descendants("Items")
.Select(item => new
{
First = item.Get("First", ""),
Second= item.Get("Second", ""),
Third = item.Get("Third", "")
});
<> p> >每个<代码>第一< /代码>,<代码>第二版>代码> <代码>第三> /代码>元素将使用<代码>项目> /COD>元素的命名空间,以确定其自己的命名空间。 您可以考虑以下选项:
local-name()
,这将
忽略名称空间var xmlDoc = new XmlDocument();
xmlDoc.Load(fileLocation);
//determine whether document contains namespace
var namespaceName = "ns";
var namespacePrefix = string.Empty;
XmlNamespaceManager nameSpaceManager = null;
if (xmlDoc.FirstChild.Attributes != null)
{
var xmlns = xmlDoc.FirstChild.Attributes["xmlns"];
if (xmlns != null)
{
nameSpaceManager = new XmlNamespaceManager(xmlDoc.NameTable);
nameSpaceManager.AddNamespace(namespaceName, xmlns.Value);
namespacePrefix = namespaceName + ":";
}
}
XmlNodeList nodeList = xmlDoc.SelectNodes(string.Format("/{0}Demo/{0}Items",namespacePrefix), nameSpaceManager);
if (nodeList != null)
{
foreach (XmlNode childNode in nodeList)
{
string first = childNode.SelectSingleNode(namespacePrefix + "First", nameSpaceManager).InnerText;
string second = childNode.SelectSingleNode(namespacePrefix + "Second", nameSpaceManager).InnerText;
string third = childNode.SelectSingleNode(namespacePrefix + "Third", nameSpaceManager).InnerText;
}
}
选项2
XmlNodeList nodeList = xmlDoc.SelectNodes("/*[local-name() = 'Demo']/*[local-name() = 'Items']");
if (nodeList != null)
{
foreach (XmlNode childNode in nodeList)
{
string first = childNode.SelectSingleNode("*[local-name() = 'First']").InnerText;
string second = childNode.SelectSingleNode("*[local-name() = 'Second']").InnerText;
string third = childNode.SelectSingleNode("*[local-name() = 'Third']").InnerText;
}
}
改进Vadim的选项1,但使用XDocument(而不是XmlDocument)API和F#而不是C#:
让fileStream=File.Open(fileLocation,FileMode.Open)
让xDocument=xDocument.LoadFileStream
让我们选择=
让nsString=xDocument.Root.Name.Namespace.ToString()
如果String.IsNullOrEmpty nsString,则
Console.Error.WriteLine“警告:在xmlns attrib中找不到命名空间URL”
没有一个
其他的
让nsManager=XmlNamespaceManager(NameTable())
设nsPrefix=“x”
nsManager.AddNamespace(nsPrefix,nsString)
如果是“字符串”http://schemas.sample.data.org/2005”“那么
Console.Error.WriteLine“警告:命名空间URL与预期不匹配,查询可能导致没有元素”
一些(nsManager,sprintf“%s:”nsPrefix)
let query=“//{0}演示/{0}项”
让节点=
将nsOpt与
|无->
设fixedQuery=String.Format(查询,String.Empty)
xDocument.XPathSelectElements fixedQuery
|一些(nsManager、nsPrefix)->
设fixedQuery=String.Format(查询,nsPrefix)
xDocument.XPathSelectElements(fixedQuery,nsManager)
对于节点中的节点,请执行以下操作:
...
您可以在xml文件中提供所有名称空间
,并动态添加它们
var document = new XmlDocument();
document.LoadXml(rawData);
var nsmgr = new XmlNamespaceManager(document.NameTable);
nsmgr.AddNamespace("dpx", document.DocumentElement.NamespaceURI); //default
var attributeCollection = document.DocumentElement.Attributes;
for (int i = 0; i < attributeCollection.Count; i++)
{
var isAttribute = nsmgr.LookupNamespace(attributeCollection[i].LocalName) == null;
if (isAttribute)
nsmgr.AddNamespace(attributeCollection[i].LocalName, attributeCollection[i].Value);
}
XmlElement xmlElem = document.DocumentElement;
var node = xmlElem.SelectSingleNode(xpath, nsmgr);
var document=new XmlDocument();
LoadXml(rawData);
var nsmgr=新的XmlNamespaceManager(document.NameTable);
nsmgr.AddNamespace(“dpx”,document.DocumentElement.NamespaceURI)//违约
var attributeCollection=document.DocumentElement.Attributes;
for(int i=0;i
如果XML中的节点没有
前缀
,则在提供路径时,应为它们提供默认前缀
。不使用XDocument的原因是什么?这使得一切,特别是名称空间,变得容易多了。好吧,它不是真正的复制品。但是,请更清楚地说明什么对您当前的方法有效,什么对您当前的方法无效。@HenkHolterman,它实际上不必只是XmlDocument。我愿意接受任何其他建议。我想我把它放在问题中,因为这是我实现的。为了澄清我的问题,我目前的方法没有那么好用,因为名称空间是硬编码的。我需要摆脱它,使它能够与任何xml文件一起工作。非常感谢你的回答。我正在马上实现它,并会让你知道它是如何工作的。我尝试了这两个选项,它们工作得很好。非常感谢你。我接受了这个答案因为它很简单并且解释得很好。关于实现选项2,有一个简单的问题,在我们处理名称空间时,有没有办法忽略节点“Demo”呢?假设“Demo”是自动生成的,并且不是常量..下次它将有另一个唯一的名称。但是内部节点将始终称为“Items”。是否可以忽略实现中的“Demo”但仍然解析文件?当然,xpath/*[local-name()='Items']
会起作用,例如:XmlNodeList nodeList=xmlDoc.SelectNodes(“/*[local-name()='Items']”)代码>我还实现了最后一个部分,它可以正常工作。这就是我现在拥有的:xmlDoc.SelectNodes(“//*[local-name()='Items']”);选项2很好,这样,你可以用多个名称空间解析它,效果很好。@Chuck Savage谢谢你的回复。我很感激。
var document = new XmlDocument();
document.LoadXml(rawData);
var nsmgr = new XmlNamespaceManager(document.NameTable);
nsmgr.AddNamespace("dpx", document.DocumentElement.NamespaceURI); //default
var attributeCollection = document.DocumentElement.Attributes;
for (int i = 0; i < attributeCollection.Count; i++)
{
var isAttribute = nsmgr.LookupNamespace(attributeCollection[i].LocalName) == null;
if (isAttribute)
nsmgr.AddNamespace(attributeCollection[i].LocalName, attributeCollection[i].Value);
}
XmlElement xmlElem = document.DocumentElement;
var node = xmlElem.SelectSingleNode(xpath, nsmgr);