为什么我无法使用XPath访问这些节点内容?

时间:2014-03-06 10:40:39

标签: c# xml xslt xpath xml-parsing

我在 XPath C#中相当新,我遇到以下问题:

我必须解析此文件:http://static.nvd.nist.gov/feeds/xml/cpe/dictionary/official-cpe-dictionary_v2.3.xml

正如您在浏览器中看到的那样,此文件具有以下结构:

<?xml version='1.0' encoding='UTF-8'?>
<cpe-list xmlns:meta="http://scap.nist.gov/schema/cpe-dictionary-metadata/0.2" xmlns:config="http://scap.nist.gov/schema/configuration/0.1" xmlns:ns6="http://scap.nist.gov/schema/scap-core/0.1" xmlns:scap-core="http://scap.nist.gov/schema/scap-core/0.3" xmlns="http://cpe.mitre.org/dictionary/2.0" xmlns:cpe-23="http://scap.nist.gov/schema/cpe-extension/2.3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://scap.nist.gov/schema/configuration/0.1 http://nvd.nist.gov/schema/configuration_0.1.xsd http://cpe.mitre.org/dictionary/2.0 http://scap.nist.gov/schema/cpe/2.3/cpe-dictionary_2.3.xsd http://scap.nist.gov/schema/scap-core/0.3 http://nvd.nist.gov/schema/scap-core_0.3.xsd http://scap.nist.gov/schema/scap-core/0.1 http://nvd.nist.gov/schema/scap-core_0.1.xsd http://scap.nist.gov/schema/cpe-dictionary-metadata/0.2 http://nvd.nist.gov/schema/cpe-dictionary-metadata_0.2.xsd http://scap.nist.gov/schema/cpe-extension/2.3 http://scap.nist.gov/schema/cpe/2.3/cpe-dictionary-extension_2.3.xsd">
  <generator>
    <product_name>National Vulnerability Database (NVD)</product_name>
    <product_version>2.22.0-SNAPSHOT (PRODUCTION)</product_version>
    <schema_version>2.3</schema_version>
    <timestamp>2014-03-05T05:13:33.550Z</timestamp>
  </generator>
  <cpe-item name="cpe:/a:1024cms:1024_cms:0.7">
    <title xml:lang="en-US">1024cms.org 1024 CMS 0.7</title>
    <cpe-23:cpe23-item name="cpe:2.3:a:1024cms:1024_cms:0.7:*:*:*:*:*:*:*"/>
  </cpe-item>
  <cpe-item name="cpe:/a:1024cms:1024_cms:1.2.5">
    <title xml:lang="en-US">1024cms.org 1024 CMS 1.2.5</title>
    <cpe-23:cpe23-item name="cpe:2.3:a:1024cms:1024_cms:1.2.5:*:*:*:*:*:*:*"/>
  </cpe-item>
  <cpe-item name="cpe:/a:1024cms:1024_cms:1.3.1">
    <title xml:lang="en-US">1024cms.org 1024 CMS 1.3.1</title>
    <cpe-23:cpe23-item name="cpe:2.3:a:1024cms:1024_cms:1.3.1:*:*:*:*:*:*:*"/>
  </cpe-item>

  .............................................................
  .............................................................
  .............................................................

  <cpe-item name="cpe:/h:zyxel:p-660hw_t3:v2">
    <title xml:lang="en-US">ZyXEL P-660HW T3 Model v2</title>
    <cpe-23:cpe23-item name="cpe:2.3:h:zyxel:p-660hw_t3:v2:*:*:*:*:*:*:*"/>
  </cpe-item>
</cpe-list>

现在,使用 XPath ,我必须获取所有 标记的列表(不包括位于第一个标记的第一个 标记到我的标记中) 标记

在我的代码中,我有类似的东西:

       XmlDocument document = new XmlDocument();    // Represent an XML document
       document.Load(sourceXML.FullName);       // Loads the XML document from the specified stream

       // Add the namespaces:
       XmlNamespaceManager nsmgr = new XmlNamespaceManager(document.NameTable);
       nsmgr.AddNamespace("ns6", "http://scap.nist.gov/schema/scap-core/0.1");
       nsmgr.AddNamespace("cpe-23", "http://scap.nist.gov/schema/cpe-extension/2.3");
       nsmgr.AddNamespace("ns", "http://cpe.mitre.org/dictionary/2.0");
       nsmgr.AddNamespace("meta", "http://scap.nist.gov/schema/cpe-dictionary-metadata/0.2");
       nsmgr.AddNamespace("scap-core", "http://scap.nist.gov/schema/scap-core/0.3");
       nsmgr.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
       nsmgr.AddNamespace("config", "http://scap.nist.gov/schema/configuration/0.1");



       /* nodeList is the collection that contains all the <cpe-item> tag that are
         * inside the root <cpe-list> tag in the XML document: 
         */
       XmlNodeList nodeList;
       nodeList = document.DocumentElement.SelectNodes("//ns:cpe-list/ns:cpe-item", nsmgr);
       long conta = 0;

所以我使用此行来选择 标记中的所有 标记:

nodeList = document.DocumentElement.SelectNodes("//ns:cpe-list/ns:cpe-item", nsmgr);

它似乎工作,但我不确定它是否正确,因为当我调查使用Visual Studio Debugger它告诉我,我的 XmlNodeList nodeList 包含:80588元素(该文件非常很大,但在我看来很多元素!!!)

另一个疑问与使用我的previouse代码中的 ns 命名空间有关(这不是我的代码,我必须处理它)。

为什么在前面的代码中, cpe-list cpe-item 前面有 ns 名称空间,如果在XML代码中要解析我有类似的东西:

  <cpe-item name="cpe:/a:1024cms:1024_cms:1.3.1">
    <title xml:lang="en-US">1024cms.org 1024 CMS 1.3.1</title>
    <cpe-23:cpe23-item name="cpe:2.3:a:1024cms:1024_cms:1.3.1:*:*:*:*:*:*:*"/>
  </cpe-item>

不以 ns 名称空间开头?为什么使用它?

最后一个问题是如何访问标题内部文字内容?

我正在尝试做这样的事情,但这样做不起作用:

XmlNodeList nodeList;
nodeList = document.DocumentElement.SelectNodes("//ns:cpe-list/ns:cpe-item", nsmgr);
long conta = 0;

DataModel.Vulnerability.CPE currentCPE;

foreach (XmlNode node in nodeList)
{
    // Access to the name ATTRIBUTE of the <cpe-item> tag:
    Debug.WriteLine(String.Format("[{0:N0}] CPE: {1}  Title: {2}", conta, node.Attributes["name"].Value, node.FirstChild.FirstChild.Value));

    // Access to the <title> tag content:
    //Debug.WriteLine(String.Format("[{0:N0}] Title: {1}  Title: {2}", conta, node.SelectSingleNode("./title", nsmgr)));
    XmlNode titleNode = node.SelectSingleNode("./title", nsmgr);

    conta++;
 }

执行此代码时,我可以将当​​前cpe元素的名称属性访问到我的列表中,但我无法访问 tag,因为执行此行时:

 XmlNode titleNode = node.SelectSingleNode("./title", nsmgr);

返回值 null

有什么问题?我错过了什么?我怎么解决?

TNX

安德烈

1 个答案:

答案 0 :(得分:2)

  1. 根据此问题中发布的XML片段,您的XPath看起来很不错。就我所见,它应该返回正确数量的元素。不能说清楚,你应该自己检查一下。
  2. 您的XML具有默认命名空间(xmlns=".....")。 XML中没有前缀的所有元素都在默认命名空间中考虑但是在XPath中,没有考虑前缀的所有元素都没有命名空间。最后,两个平台的不同范例都要求您定义指向默认命名空间URL的ns前缀,以便在XPath语句中使用。
  3. 与第2点相关。请记住,所有没有前缀的元素都在默认命名空间中。 <title>元素也是如此。因此,您需要在XPath语句中添加ns前缀:./ns:title
  4. 理想情况下,一个帖子必须包含不超过一个特定问题。在一篇文章中回答一堆问题对于未来的访问者来说很少有用,而是倾向于混淆他们。请记住,我们不仅要在这里解决您的问题,还要努力建立知识库,希望对有类似问题的其他人有用。