Подтвердить что ты не робот

Как запросить пространство имен по умолчанию с помощью MSXML

У меня есть XML:

<?xml version="1.0" ?>
<Project ToolsVersion="4.0">
    <PropertyGroup Condition="'$(key)'=='1111'">
          <Key>Value</Key>
    </PropertyGroup>
</Project>

Примечание. Это не фактический XML, который я использую, он просто красивее и короче и демонстрирует проблему.

Используя MSXML, я могу запросить узлы:

IXMLDOMNode node = doc.selectSingleNode("//PropertyGroup/@Condition");

И он отлично работает:

Condition = "'$ (ключ)' == '1111'"

Но на самом деле XML не имеет

В действительности XML я содержит объявление пространства имен:

XMLNS = "http://schemas.microsoft.com/developer/msbuild/2003"

создание документа фактического:

<?xml version="1.0" ?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup Condition="'$(key)'=='1111'">
          <Key>Value</Key>
    </PropertyGroup>
</Project>

Теперь мой запрос:

IDOMNode node = doc.selectSingleNode("//PropertyGroup/@Condition");

не возвращает совпадающих узлов.

Как мне запросить пространство имен по умолчанию с помощью MSXML?

Примечание

  • i уже знаю как запросить пространство имен не по умолчанию в xml; вы используете:

       doc.setProperty("SelectionNamespaces", 
             "xmlns="http://schemas.microsoft.com/developer/msbuild/2003");
    
  • Я уже знаю как запросить пространство имен по умолчанию в .NET. Вы используете диспетчер пространства имен, задаете пространство имен по умолчанию, а затем запрашиваете это имя, затем вы можете запросить пространство имен, отличное от значения по умолчанию, поскольку оно больше не используется по умолчанию

  • i может просто удалить текст оскорбительного xmlns из строки XML, которую я получаю, но я предпочел бы "сделать это правильно"

Как я могу запросить "по умолчанию" или "неназванное" пространство имен с помощью MSXML?


Примечание: на самом деле XML я использую SQL Server XML ShowPlan:

<?xml version="1.0" encoding="UTF-16" standalone="yes"?>
   <ShowPlanXML Version="1.1" Build="10.50.1600.1" 
                   xmlns="http://schemas.microsoft.com/sqlserver/2004/07/showplan">
      <BatchSequence>
           <Batch>
           ...
           </Batch>
      </BatchSequence>
   </ShowPlanXML> 

Снова вы можете увидеть объявление о запрещении имен. Удаление этого работает, но это утомительно.

Что еще вы пробовали?

Я также попытался установить SelectionNamespace:

doc.setProperty('SelectionNamespaces', 
      'xmlns="http://schemas.microsoft.com/developer/msbuild/2003"');

как Microsoft намекает на статью в статье.

Как получить пространство имен по умолчанию?

В действительности я не забочусь о пространствах имен. Мой запрос имеет смысл, и я хочу, чтобы он работал. Итак, другой подход к вопросу может быть следующим:

Как я могу запросить пространство имен по умолчанию, независимо от того, какое имя пространства имен (или нет), или нет?

Примечание: msxml - это собственный код и его использование из собственного компилятора Win32 (т.е. нет .NET framework или CLR)

4b9b3361

Ответ 1

Явно укажите имя пространства имен при добавлении его в SelectionNamespaces:

doc.setProperty("SelectionNamespaces",
      "xmlns:peanut='http://schemas.microsoft.com/developer/msbuild/2003'");

а затем выполните запрос с использованием этого пространства имен:

IDOMNode node = doc.selectSingleNode("//peanut:PropertyGroup/@Condition");

В этом пространстве имен вы можете указать любое сокращенное имя (peanut в этом случае). А затем используйте аббревиатуру как префикс (peanut:PropertyGroup в этом случае).

Предыдущие предложения

Я бы попытался перейти к Xml.Linq.

Вот пример (с пространством имен).

      try
    {

        XDocument xDoc1 = XDocument.Parse("<?xml version=\"1.0\" ?><Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\"><PropertyGroup Condition=\"'$(key)'=='1111'\"><Key>Value</Key></PropertyGroup></Project>");
        XNamespace ns1 = XNamespace.Get("http://schemas.microsoft.com/developer/msbuild/2003");

        var list1 = from list in xDoc1.Descendants(ns1 + "Project")
                    from item in list.Elements(ns1 + "PropertyGroup")
                    /* where item.Element(ns + "HintPath") != null */
                    where item.Attribute("Condition") != null
                    select new
                    {
                        MyCondition = item.Attribute("Condition") == null ? "Not Here!" : item.Attribute("Condition").Value,
                        MyFake = item.Attribute("DoesNotExistTest") == null ? "Not Here Sucker!" : item.Attribute("DoesNotExistTest").Value
                    };


        foreach (var v in list1)
        {
            Console.WriteLine(v.ToString());
        }


        XDocument xDoc2 = XDocument.Parse("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"yes\"?>   <ShowPlanXML Version=\"1.1\" Build=\"10.50.1600.1\"                    xmlns=\"http://schemas.microsoft.com/sqlserver/2004/07/showplan\">      <BatchSequence>            <Batch>Something I Threw In Here</Batch>      </BatchSequence>    </ShowPlanXML> ");
        XNamespace ns2 = XNamespace.Get("http://schemas.microsoft.com/sqlserver/2004/07/showplan");

        var list2 = from list in xDoc2.Descendants(ns2 + "ShowPlanXML")
                    from item in list.Elements(ns2 + "BatchSequence")
                    /*                             where item.Attribute("Condition") != null */
                    where item.Element(ns2 + "Batch") != null 
                    select new
                    {
                        BatchValue = (item.Element(ns2 + "Batch") == null) ? string.Empty : item.Element(ns2 + "Batch").Value
                    };


        foreach (var v in list2)
        {
            Console.WriteLine(v.ToString());
        }



    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }