C# 使用XPath和C处理IMSManifest.xml#
我不熟悉XPath,我正在寻找关于从文件中简单选择三个值的指导:schemaversion、title和description 当我从C# 使用XPath和C处理IMSManifest.xml#,c#,.net,xml,xpath,C#,.net,Xml,Xpath,我不熟悉XPath,我正在寻找关于从文件中简单选择三个值的指导:schemaversion、title和description 当我从和中去掉名称间距信息时,Xpath表达式//title/langstring仅与元素值匹配 在内容中搜索这些值的正确方法是什么 单元测试: [Test] public void TitleIsNotNull() { var manifestManager = new ManifestManager("imsmanifest.xml"); // Code w
和
中去掉名称间距信息时,Xpath表达式//title/langstring
仅与元素值匹配
在内容中搜索这些值的正确方法是什么
单元测试:
[Test]
public void TitleIsNotNull()
{
var manifestManager = new ManifestManager("imsmanifest.xml");
// Code which initializes object and calls GetTitle() is encapsulated.
Assert.IsNotNullOrEmpty(manifestManager.Title);
}
正在测试的系统:
private string GetTitle()
{
var document = XElement.Parse(_contents);
const string XpathExpression = "//title/langstring";
return (string)document.XPathSelectElement(XpathExpression);
}
_内容(节选):
//私人助手
private XmlReader GetXmlReader()
{
var contents = new StringReader(_contents);
var xmlReader = XmlReader.Create(contents);
return xmlReader;
}
private XmlNamespaceManager GetXmlNamespaceManager(XmlReader xmlReader)
{
if (xmlReader.NameTable != null)
{
var xmlNamespaceManager = new XmlNamespaceManager(xmlReader.NameTable);
xmlNamespaceManager.AddNamespace("x", "http://www.imsproject.org/xsd/imscp_rootv1p1p2");
xmlNamespaceManager.AddNamespace("y", "http://www.imsglobal.org/xsd/imsmd_rootv1p2p1");
return xmlNamespaceManager;
}
return null;
}
您遇到的问题是,您试图选择的元素实际上属于某个名称空间,但您在选择它时没有指定名称空间。
title
和langstring
元素都属于默认名称空间。在XML文档中,默认名称空间定义为”http://www.imsproject.org/xsd/imscp_rootv1p1p2“
。使用XPath,无法指定默认名称空间。如果您不提供名称空间,它总是假定您根本没有名称空间。因此,要选择该元素,必须显式提供名称空间,如下所示:
XmlNamespaceManager namespaceManager = new XmlNamespaceManager(nameTable);
namespaceManager.AddNamespace("x", "http://www.imsproject.org/xsd/imscp_rootv1p1p2");
const string XpathExpression = "//x:title/x:langstring";
return (string)document.XPathSelectElement(XpathExpression, namespaceManager);
XmlReader reader = XmlReader.Create(new StringReader(_contents));
XElement document = XElement.Load(reader);
XmlNamespaceManager namespaceManager = new XmlNamespaceManager(reader.NameTable);
namespaceManager.AddNamespace("x", "http://www.imsproject.org/xsd/imscp_rootv1p1p2");
const string XpathExpression = "//x:title/x:langstring";
return (string)document.XPathSelectElement(XpathExpression, namespaceManager);
然而,诀窍是让XmlNameTable
提供给XmlNamespaceManager
。不幸的是,XElement
类没有为文档提供获取XmlNameTable
的方法,因此最好通过XmlReader
加载它,它可以提供如下功能:
XmlNamespaceManager namespaceManager = new XmlNamespaceManager(nameTable);
namespaceManager.AddNamespace("x", "http://www.imsproject.org/xsd/imscp_rootv1p1p2");
const string XpathExpression = "//x:title/x:langstring";
return (string)document.XPathSelectElement(XpathExpression, namespaceManager);
XmlReader reader = XmlReader.Create(new StringReader(_contents));
XElement document = XElement.Load(reader);
XmlNamespaceManager namespaceManager = new XmlNamespaceManager(reader.NameTable);
namespaceManager.AddNamespace("x", "http://www.imsproject.org/xsd/imscp_rootv1p1p2");
const string XpathExpression = "//x:title/x:langstring";
return (string)document.XPathSelectElement(XpathExpression, namespaceManager);
或者,您可以使用
XmlDocument
,这在处理名称空间时稍微容易一些。或者,您也可以选择使用LINQ来选择元素,而不是XPath。Steven我不确定我搞错了什么,但该值返回null并且未通过我的测试。为了让它在我这方面起作用,我还必须删除schemalocation
属性。试试看它是否能帮你解决问题。如果是这样的话,那就是问题的第二部分所在。我能够添加一个新的名称空间声明xmlNamespaceManager.AddNamespace(“y”)http://www.imsglobal.org/xsd/imsmd_rootv1p2p1");
查找嵌套在
元素下的元素。我修改了我的问题,加入了你的修正,我接受了你的回答。非常感谢。