对如何解析带有命名空间前缀的 xml 感到非常困惑

Very confused about how to parse xml with namespace prefixes

提问人:Levi Wallach 提问时间:11/1/2011 最后编辑:John SaundersLevi Wallach 更新时间:11/1/2011 访问量:3009

问:

因此,我需要能够解析可能包含命名空间前缀的 xml 文件。我尝试使用示例文件执行此操作,并且在尝试获取节点列表时,即使我指定了一个没有属性前缀的节点,它也会返回 null。

我一直在尝试对此进行研究,它不断回到这样一个事实,即如果不定义命名空间前缀,它将无法工作,因此我添加了我认为可以执行此操作的代码,但它仍然给出相同的结果。这是我添加的一些代码:

protected void Page_Load(object sender, EventArgs e)
{
    xml.Load(Server.MapPath("~/SomeLesson/imsmanifest.xml"));
    populateBaseNodes();
}

private void populateBaseNodes()
{
    treeViewMenu.Nodes.Clear(); // Clear any existing items
    TreeNode treenode = new TreeNode();
    treenode.Text = "organizations";
    XmlNodeList baseNodeList;

    string xmlns = xml.DocumentElement.Attributes["xmlns"].Value;
    XmlNamespaceManager nsmgr = new XmlNamespaceManager(xml.NameTable);
    nsmgr.AddNamespace("adlcp", "http://www.adlnet.org/xsd/adlcp_v1p3");
    nsmgr.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
    nsmgr.AddNamespace("imscp", "http://www.w3.org/2001/XMLSchema-instance");
    nsmgr.AddNamespace("imsss", "http://www.w3.org/2001/XMLSchema-instance");
    nsmgr.AddNamespace("schemaLocation", "http://www.w3.org/2001/XMLSchema-instance");

    baseNodeList = xml.SelectNodes("/manifest/organizations/organization/item", nsmgr);

    TextBox1.Text = baseNodeList.Count.ToString();

    foreach (XmlNode xmlnode in baseNodeList)
    {
        TreeNode treeNodeCatalog = new TreeNode();
        treeNodeCatalog.Text = xmlnode.Attributes["identifier"].Value;
        treeNodeCatalog.SelectAction = TreeNodeSelectAction.Expand;
        treeViewMenu.Nodes.Add(treeNodeCatalog);
    }

    treeViewMenu.CollapseAll();
}

(marc_s)下面是需要解析的有问题的 XML:

<manifest identifier="Navigating_in_QuickBooks_-_Introduction_MANIFEST" version="1.3"
  xmlns="http://www.imsglobal.org/xsd/imscp_v1p1"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:imscp="http://www.imsglobal.org/xsd/imscp_v1p1"
    xmlns:adlcp="http://www.adlnet.org/xsd/adlcp_v1p3" 
    xmlns:imsss="http://www.imsglobal.org/xsd/imsss"
    xsi:schemaLocation=" http://www.imsglobal.org/xsd/imscp_v1p1 imscp_v1p1.xsd
                         http://www.imsglobal.org/xsd/imsss imsss_v1p0.xsd
                         http://www.adlnet.org/xsd/adlcp_v1p3 adlcp_v1p3.xsd 
                         http://www.adlnet.org/xsd/adlseq_v1p3 adlseq_v1p3.xsd
                         http://www.adlnet.org/xsd/adlnav_v1p3 adlnav_v1p3.xsd">

  <metadata>  
     <!-- not relevant here ... -->
  </metadata>
  <organizations default="TOC1">
     <organization identifier="TOC1">
        <title>Navigating in QuickBooks - Introductory Lesson</title>
        <item identifier="I_SCO0" identifierref="SCO0"> 
            <title>Navigating in QuickBooks - Introductory Lesson</title>
        </item>
     </organization>
   </organizations>
   <resources>
     <!-- not relevant here ... -->
   </resources>
</manifest>
asp.net xml

评论


答:

4赞 marc_s 11/1/2011 #1

您不是在向我们展示您的 XML 是什么样子的 - 而是两条评论:

  1. 你不需要添加前缀,我不确定前缀应该做什么......xsischemaLocation

  2. 当你定义了架构前缀后,当然,你还需要在你的 XPath 中使用这些前缀!

同样,不知道您的 XML 结构是什么样子的,我无法真正告诉您需要什么 - 但大致如下:

 baseNodeList = xml.SelectNodes("/adlcp:manifest/adlcp:organizations/adlcp:organization/imscp:item", nsmgr);

或源 XML 所需的任何其他 XML 命名空间前缀。

更新:看到你的 XML 会更清晰:看到根节点 - 它有一个默认的 XML 命名空间(带有且没有显式前缀的命名空间):xmlns="...."

<manifest identifier="Navigating_in_QuickBooks_-_Introduction_MANIFEST" version="1.3"
     xmlns="http://www.imsglobal.org/xsd/imscp_v1p1"  <=== DEFAULT namespace!!!
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:imscp="http://www.imsglobal.org/xsd/imscp_v1p1"
     xmlns:adlcp="http://www.adlnet.org/xsd/adlcp_v1p3" 
     xmlns:imsss="http://www.imsglobal.org/xsd/imsss"
    ................>

这意味着:所有没有特定 XML 前缀的后续节点都将位于该默认命名空间中

不幸的是,.NET XML 解析在定义没有前缀的默认命名空间时存在问题 - 所以我最好的解决方案是创建一个带有默认命名空间前缀的命名空间,然后使用它:

XmlNamespaceManager nsmgr = new XmlNamespaceManager(xml.NameTable);

// add default namespace, with a prefix for .NET 
nsmgr.AddNamespace("ns", "http://www.imsglobal.org/xsd/imscp_v1p1");

baseNodeList = 
   xml.SelectNodes("/ns:manifest/ns:organizations/ns:organization/ns:item", nsmgr);

你现在得到任何结果了吗??

评论

0赞 Levi Wallach 11/1/2011
对不起,这是 xml,其中包含一些通用的东西以保护无辜者 ;-)
0赞 Levi Wallach 11/1/2011
问题是,在 xml 中,整个文档中使用的唯一前缀是在我没有解析的节点中,它只使用 adcp。我正在解析的节点中没有前缀,所以我在 Xpath 中使用它没有意义,是吗?
0赞 Levi Wallach 11/1/2011
如果删除这个问题并且我可以将其与 xml 一起重新发布,也许会更好?
0赞 marc_s 11/1/2011
@LeviWallach:根节点上没有任何XML命名空间前缀吗?你不能把你的XML剪下来并发布在这里吗?这将是非常有帮助的!我们不需要所有的细节(所有的节点) - 但它的要点会非常有帮助......
0赞 Levi Wallach 11/1/2011
当然,我会尝试:<manifest identifier=“Introduction_MANIFEST” version=“1.3” xmlns=“imsglobal.org/xsd/imscp_v1p1” xmlns:xsi=“w3.org/2001/XMLSchema-instance” xmlns:imscp=“imsglobal.org/xsd/imscp_v1p1” xmlns:adlcp=“adlnet.org/xsd/adlcp_v1p3” xmlns:imsss=“imsglobal.org/xsd/imsss” xsi:schemaLocation=“ imsglobal.org/xsd/imscp_v1p1 imscp_v1p1.xsd imsglobal.org/xsd/imsss imsss_v1p0.xsd adlnet.org/xsd/adlcp_v1p3 adlcp_v1p3.xsd>
0赞 pmartin 11/1/2011 #2

在您发布的 XML 中,控制示例文件中所有元素的默认命名空间为:

xmlns="http://www.imsglobal.org/xsd/imscp_v1p1" 

此命名空间不定义前缀,因此必须使用空白前缀将此命名空间添加到命名空间管理器中。我认为您应该能够使用此代码来定义默认命名空间(使用 String.Empty 指定空白前缀):

nsmgr.AddNamespace(String.Empty, "http://www.imsglobal.org/xsd/imscp_v1p1");

评论

0赞 marc_s 11/1/2011
你会认为这种方法会起作用 - 但在 .NET XML 解析中,它不会;如果您尝试使用此 XML 文件,即使一切似乎都已正确设置,您也会返回一个空的 XML 节点列表.....