关于如何用名称空间前缀解析xml非常困惑

时间:2011-10-31 18:13:56

标签: asp.net xml

因此,我需要能够解析可能包含名称空间前缀的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>

2 个答案:

答案 0 :(得分:4)

您没有向我们展示您的XML是什么样的 - 但有两条评论:

  1. 您不需要添加xsi前缀,我不确定schemaLocation前缀应该做什么....

  2. 当您定义架构前缀时,您还需要在您的XPath中使用这些前缀!

  3. 同样,不知道你的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"
        ................>
    

    这意味着: ALL 您的后续节点没有特定的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);
    

    你现在得到任何结果吗?

答案 1 :(得分:0)

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

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

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

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