Вопрос по xml – Что не так с моим XPath / XML?

10

Я пробую очень простой XPath на этот xml (так же, как ниже), и ничего не находит. Я пытаюсь как .NET и этот сайт и XPaths, такие как//PropertyGroup, /PropertyGroup а также//MSBuildCommunityTasksPath просто не работают для меня (они скомпилированы, но возвращают ноль результатов).

Исходный XML:

<code><?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <!-- $Id: FxCop.proj 114 2006-03-14 06:32:46Z pwelter34 $ -->
    <PropertyGroup>
        <MSBuildCommunityTasksPath>$(MSBuildProjectDirectory)\MSBuild.Community.Tasks\bin\Debug</MSBuildCommunityTasksPath>
    </PropertyGroup>
    <Import
        Project="$(MSBuildProjectDirectory)\MSBuild.Community.Tasks\MSBuild.Community.Tasks.Targets" />
    <Target Name="DoFxCop">
        <FxCop TargetAssemblies="$(MSBuildCommunityTasksPath)\MSBuild.Community.Tasks.dll"
            RuleLibraries="@(FxCopRuleAssemblies)" 
            AnalysisReportFileName="Test.html"
            DependencyDirectories="$(MSBuildCommunityTasksPath)" 
            FailOnError="True"
            ApplyOutXsl="True"
            OutputXslFileName="C:\Program Files\Microsoft FxCop 1.32\Xml\FxCopReport.xsl" />
    </Target>
</Project>
</code>
Если бы вы могли предоставить краткий пример кода того, что вы пробовали в .net, вам будет легче подсказать, что может пойти не так. morechilli

Ваш Ответ

3   ответа
16

но вы можете эффективно подстановить пространство имен. Попробуйте следующую идиому XPath.

//*[local-name()='PropertyGroup']
//*[local-name()='MSBuildCommunityTasksPath']

name () обычно работает так же, как и в:

//*[name()='PropertyGroup']
//*[name()='MSBuildCommunityTasksPath']

РЕДАКТИРОВАТЬ: Пространства отличные и я не предполагаю, что они не важны, но подстановочные знаки их пригодятся при объединении кода прототипа, одноразовых инструментов рабочего стола, экспериментов с XSLT и так далее. Соотнесите свою потребность в удобстве с приемлемым риском для поставленной задачи. К вашему сведению, при необходимости вы также можете лишить или переназначить пространства имен.

Спасибо! Вы не представляете, как долго я охотился за этим ответом. Brilliant! Gerard
Этот ответ только что решил проблему, спасибо! Abel Morelos
@ Абель Морелос - рад, что это помогло; когда я наконец обнаружил это много лун назад, это заставило работать XMта намного легче b w
@ grantwparks - я не говорю, что пространства имен не ценны, но иногда необходимо создать преобразование, которое игнорирует их, а иногда просто удобно не иметь с ними дело. В любом случае, это решение пригодится. b w
Неквалификация - это плохо. Это эквивалентно запросу столбцов из СУБД без указания каких таблиц. Как одна строка кода для каждого объявления префикса превращается в «и все такое»? grantwparks
2

созданное атрибутом xmlns без префикса. К сожалению, XPath не может запрашивать элементы в пространстве имен по умолчанию. Я на самом деле не уверен в семантических деталях, но вы должны явно прикрепить префикс к этому пространству имен, используя любой инструмент, на котором размещается XPath.

В .NET может быть более короткий способ сделать это, но я видел только один способ - через NameSpaceManager. После явного добавления пространства имен вы можете выполнять запросы с помощью диспетчера пространства имен, как если бы все теги в элементе пространства имен имели этот префикс (я выбрал «msbuild»):

using System;
using System.Xml;

public class XPathNamespace {
    public static void Main(string[] args) {
        XmlDocument xmlDocument = new XmlDocument();
        xmlDocument.LoadXml(
    @"<?xml version=""1.0"" encoding=""utf-8""?>
<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
    <!-- $Id: FxCop.proj 114 2006-03-14 06:32:46Z pwelter34 $ -->

    <PropertyGroup>
        <MSBuildCommunityTasksPath>$(MSBuildProjectDirectory)\MSBuild.Community.Tasks\bin\Debug</MSBuildCommunityTasksPath>
    </PropertyGroup>

    <Import Project=""$(MSBuildProjectDirectory)\MSBuild.Community.Tasks\MSBuild.Community.Tasks.Targets""/>

    <Target Name=""DoFxCop"">

        <FxCop 
            TargetAssemblies=""$(MSBuildCommunityTasksPath)\MSBuild.Community.Tasks.dll""
            RuleLibraries=""@(FxCopRuleAssemblies)"" 
            AnalysisReportFileName=""Test.html""
            DependencyDirectories=""$(MSBuildCommunityTasksPath)""
            FailOnError=""True""
            ApplyOutXsl=""True""
            OutputXslFileName=""C:\Program Files\Microsoft FxCop 1.32\Xml\FxCopReport.xsl""
        />
    </Target>

</Project>");

        XmlNamespaceManager namespaceManager = new
    XmlNamespaceManager(xmlDocument.NameTable);
        namespaceManager.AddNamespace("msbuild", "http://schemas.microsoft.com/developer/msbuild/2003");
        foreach (XmlNode n in xmlDocument.SelectNodes("//msbuild:MSBuildCommunityTasksPath", namespaceManager)) {
            Console.WriteLine(n.InnerText);
        }
    }
}
1

http://schemas.microsoft.com/developer/msbuild/2003"). Вы получаете ноль узлов, потому что вы не квалифицируете его с пространством имен. Если вы удалите атрибут xmlns, ваш XPath «// PropertyGroup» будет работать. То, как вы делаете запрос с пространством имен, обычно включает в себя наложение псевдонима xmlns по умолчанию на идентификатор (так как он не указан в атрибуте) и выбор типа "//myXMLNStoken:PropertyGroup"

Похожие вопросы