Очень смущен тем, как анализировать xml с помощью префиксов пространства имен

#asp.net #xml

#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>
 

Ответ №1:

Вы не показываете нам, как выглядит ваш XML, но два комментария:

  1. вам не нужно добавлять xsi префикс, и я не уверен, что schemaLocation должен делать префикс….
  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);
 

Вы получаете какие-либо результаты сейчас??

Комментарии:

1. Извините, вот xml с некоторыми обобщенными материалами для защиты невинных 😉

2. Проблема в том, что в xml единственный префикс, используемый во всем документе, находится в узле, который я не анализирую, и он использует только adcp. В узле, который я анализирую, нет префиксов, поэтому не имеет смысла использовать его в Xpath, не так ли??

3. Возможно, было бы лучше, если бы этот вопрос был удален, и я мог бы опубликовать его вместе с xml?

4. @LeviWallach: у корневого узла нет префиксов пространств имен XML на нем?? Разве вы не можете просто обрезать свой XML и опубликовать его здесь?? Это было бы весьма полезно! Нам не нужны все детали (все узлы), но суть этого была бы очень полезна…

5. конечно, я попробую: <идентификатор манифеста=»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:Расположение схемы=» imsglobal.org/xsd/imscp_v1p1 imscp_v1p1.xsdimsglobal.org/xsd/imsss imsss_v1p0.xsd adlnet.org/xsd/adlcp_v1p3 adlcp_v1p3.xsd>


Ответ №2:

В XML, который вы опубликовали, пространство имен по умолчанию, управляющее всеми элементами в вашем примере файла:

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

Это пространство имен не определяет префикс, поэтому вы должны добавить это пространство имен в свой диспетчер пространств имен, используя пустой префикс. Я думаю, вы должны иметь возможность использовать этот код для определения пространства имен по умолчанию (используя String .Пустой, чтобы указать пустой префикс):

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

Комментарии:

1. Вы могли бы ПОДУМАТЬ , что этот подход будет работать, но при синтаксическом анализе .NET XML это не так ; если вы попробуете это с этим XML-файлом, даже если кажется , что все настроено правильно, вы получите пустой список XML-узлов…..