从XML文件中读取节点在XMLDocument中

4

我正在尝试获取TopicName,但是我应该如何去尝试不同的组合呢?不过无论如何,我都无法得到TopicName。以下是我的源代码...

XmlDocument xdoc = new XmlDocument();//xml doc used for xml parsing

    xdoc.Load(
        "http://latestpackagingnews.blogspot.com/feeds/posts/default"
        );//loading XML in xml doc

    XmlNodeList xNodelst = xdoc.DocumentElement.SelectNodes("content");//reading node so that we can traverse thorugh the XML

    foreach (XmlNode xNode in xNodelst)//traversing XML 
    {
        //litFeed.Text += "read";
    }

示例 XML 文件

<content type="application/xml">
 <CatalogItems xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="sitename.xsd">
        <CatalogSource Acronym="ABC" OrganizationName="ABC Corporation" />
        <CatalogItem Id="3212" CatalogUrl="urlname">
          <ContentItem xmlns:content="sitename.xsd" TargetUrl="url">
            <content:SelectionSpec ClassList="" ElementList="" />
            <content:Language Value="eng" Scheme="ISO 639-2" />
            <content:Source Acronym="ABC" OrganizationName="ABC Corporation" />
            <content:Topics Scheme="ABC">
              <content:Topic TopicName="Marketing" />
              <content:Topic TopiccName="Coverage" />
            </content:Topics>
          </ContentItem>
        </CatalogItem>
      </CatalogItems>
    </content>

你最新更新的示例代码中的URL生成的XML与你的示例XML完全不同,该XML中没有CatalogItem或内容命名空间。 - BrokenGlass
3个回答

8
您的XML中的Topic节点正在使用content命名空间 - 您需要在代码中声明和使用XML命名空间,然后您可以使用SelectNodes()来获取感兴趣的节点 - 这对我有效:
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xdoc.NameTable);
nsmgr.AddNamespace("content", "sitename.xsd");

var topicNodes = xdoc.SelectNodes("//content:Topic", nsmgr);

foreach (XmlNode node in topicNodes)
{
    string topic = node.Attributes["TopicName"].Value;
}

就像这个比较一样,使用Linq to XML会更加容易:

XDocument xdoc = XDocument.Load("test.xml");
XNamespace ns = "sitename.xsd";
string topic = xdoc.Descendants(ns + "Topic")
                   .Select(x => (string)x.Attribute("TopicName"))
                   .FirstOrDefault();

要获取所有主题,您可以使用以下语句替换最后一条语句:
var topics = xdoc.Descendants(ns + "Topic")
                 .Select(x => (string)x.Attribute("TopicName"))
                 .ToList();

@Abu:我测试过了,代码对我来说运行良好 - 你是否包含了命名空间管理器? - BrokenGlass
同时,这也假设您已经将XML加载到了“xdoc”中。 - BrokenGlass
如果我使用第二个选项,也就是“linq to xml”,根据你的代码,我只会得到一个topicname,但是当你遍历我的整个xml时,我会有多个topicname...只是想知道你会怎么做。 - Nick Kahn
@Abu:您的 XML 目前只有一个主题名称——我猜第二个节点中的“TopiccName”是一个错别字?- 答案已更新 - BrokenGlass
抱歉,您是正确的,这是一个打字错误,所以我总共有两个TopicName。我将尝试您提供的第二种解决方案,但是ns是什么,我知道它是指命名空间,但是它期望的命名空间是什么? - Nick Kahn
显示剩余2条评论

0
如果您只需要特定的元素,则可以使用XPath:
这是一个关于在C#中使用XPath的指南: http://www.codeproject.com/KB/XML/usingXPathNavigator.aspx 以下是可获取主题集合的查询:
//content/CatalogItems/CatalogItem/ContentItem/content:Topics/content:Topic

你可以根据你想要完成的目标来调整此查询,仅获取特定的TopicName值:
//content/CatalogItems/CatalogItem/ContentItem/content:Topics/content:Topic/@TopicName

XPath 很容易学习。我之前没有任何相关知识,也能很快地完成这样的任务。
你可以在这里粘贴你的 XML 和 XPath 查询来测试你的查询:

http://www.bit-101.com/xpath/


我尝试了第一个解决方案,但没有起作用...它返回0计数。 - Nick Kahn
如果您将 XML 和 XPath 查询复制到 XPath 工具中,应该会返回一个项,所以不确定出了什么问题。 - AaronLS
你能告诉我具体步骤吗?我试着将XML粘贴到“www.bit-101.com/xpath”工具中,然后呢?右侧显示“未定义”。 - Nick Kahn

0
以下是一个快速而简单的LINQ to XML代码,它获取您的TopicNames并将它们打印在控制台上。
XDocument lDoc = XDocument.Load(lXmlDocUri);

foreach (var lElement in lDoc.Element("content").Element(XName.Get("CatalogItems", "sitename.xsd")).Elements(XName.Get("CatalogItem", "sitename.xsd")))
{
     foreach (var lContentTopic in lElement.Element(XName.Get("ContentItem", "sitename.xsd")).Element(XName.Get("Topics", "sitename.xsd")).Elements(XName.Get("Topic", "sitename.xsd")))
     {
           string lTitle = lContentTopic.Attribute("TopicName").Value;
           Console.WriteLine(lTitle);
     }
}

如果没有所有的命名空间,它会更短 :) (而不是使用“XName.Get”,您只需使用元素的名称)。


首先抛出一个错误,foreach 循环中的错误是 对象引用未设置为对象的实例 - Nick Kahn
我的代码可以在你的样例中运行,对于一般的XML文件,其中可能没有内容节点,例如,你只需要询问lDoc.Element("content") != null。 - SoManyGoblins

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