#c# #xml-parsing
#c# #xml-синтаксический анализ
Вопрос:
Я хотел бы спросить вас о синтаксическом анализе XML, я пробую это многими способами, но никогда не получаю результат, который я «хочу/ожидаю». Я хотел бы получить ВСЕ элементы с определенным именем («PackageReference») и его атрибуты/дочерние элементы(элементы). После этого я сделаю сбор и проанализирую результат, чтобы получить значение атрибута «включить» и значение элемента/атрибута с именем «версия».
пример xml (мои элементы, которые меня интересуют, находятся внизу):
lt;?xml version="1.0" encoding="utf-8"?gt; lt;Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"gt; lt;PropertyGroupgt; lt;AutoGenerateBindingRedirectsgt;truelt;/AutoGenerateBindingRedirectsgt; lt;IsWebBootstrappergt;falselt;/IsWebBootstrappergt; lt;PublishUrlgt;publishlt;/PublishUrlgt; lt;Installgt;truelt;/Installgt; lt;UpdateIntervalUnitsgt;Dayslt;/UpdateIntervalUnitsgt; lt;/PropertyGroupgt; lt;PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhoneSimulator' "gt; lt;DebugSymbolsgt;truelt;/DebugSymbolsgt; lt;DebugTypegt;fulllt;/DebugTypegt; lt;Optimizegt;falselt;/Optimizegt; lt;/PropertyGroupgt; lt;ItemGroupgt; lt;Compile Include="Launch.cs" /gt; lt;Compile Include="Launch.designer.cs"gt; lt;DependentUpongt;Launch.cslt;/DependentUpongt; lt;/Compilegt; lt;Compile Include="Main.cs" /gt; lt;None Include="Info.plist"gt; lt;SubTypegt;Designerlt;/SubTypegt; lt;/Nonegt; lt;/ItemGroupgt; lt;ItemGroupgt; lt;Reference Include="System" /gt; lt;Reference Include="System.Core" /gt; lt;/ItemGroupgt; lt;ItemGroupgt; lt;ProjectReference Include="....ModelProject.Model.csproj"gt; lt;Projectgt;{0511395F-513C-4F56-BF87-718CA49BB13B}lt;/Projectgt; lt;Namegt;Project.Modellt;/Namegt; lt;/ProjectReferencegt; lt;/ItemGroupgt; lt;ItemGroupgt; lt;PackageReference Include="AutoMapper"gt; lt;Versiongt;7.0.1lt;/Versiongt; lt;/PackageReferencegt; lt;PackageReference Include="GMImagePicker.Xamarin"gt; lt;Versiongt;2.5.0lt;/Versiongt; lt;/PackageReferencegt; lt;PackageReference Include="IdentityModel"gt; lt;Versiongt;4.1.0lt;/Versiongt; lt;/PackageReferencegt; lt;PackageReference Include="Microsoft.AppCenter"gt; lt;Versiongt;4.3.0lt;/Versiongt; lt;/PackageReferencegt; lt;PackageReference Include="Microsoft.AppCenter.Analytics"gt; lt;Versiongt;4.3.0lt;/Versiongt; lt;/PackageReferencegt; lt;PackageReference Include="Microsoft.AppCenter.Crashes"gt; lt;Versiongt;4.3.0lt;/Versiongt; lt;/PackageReferencegt; lt;PackageReference Include="Package.Test" Version="1.1.21" /gt; lt;/ItemGroupgt; lt;ItemGroup /gt; lt;/Projectgt;
Результат должен быть:
AutoMapper;7.0.1 GMImagePicker.Xamarin;2.5.0 ... ... Package.Test;1.1.21
Мой код:
var text = System.IO.File.ReadAllText(@"C:MyGitTestXML3.csproj"); var root = XElement.Parse(text); var packageReferencesElements = root.Descendants("PackageReference"); var packageReferencesElementsAndSelf = root.DescendantsAndSelf("PackageReference"); var packageReferencesElementsOffElement = root.Elements().DescendantsAndSelf("PackageReference");
Я перепробовал много способов, и лишь немногие из них вы можете увидеть в коде. Я не хочу «заходить» в каждый элемент, у которого есть ребенок, и проверять в цикле, есть ли что-то, что меня может заинтересовать. Должен быть лучший способ. И дело в том, что я не уверен, находятся ли мои элементы, которые я ищу, в 2 слое или даже глубже.
Обновление: этот код работает, чтобы получить мою информацию, когда я знаю, насколько они глубоки… Но когда я не знаю, насколько глубоко это должно быть?
var root = XElement.Parse(fileString); var itemGroupsELements = root.Elements().Where(x =gt; x.Name.LocalName == "ItemGroup"); var packageReferenceElements = itemGroupsELements.Elements().Where(x =gt; x.Name.LocalName == "PackageReference"); foreach (var packageReference in packageReferenceElements) { string packageName = packageReference.Attribute("Include").Value; string version = (packageReference.Attribute("Version") != null) ? packageReference.Attribute("Version").Value : packageReference.Value; _packageList.Add(new Package(){App = app, PackageName = packageName, PackageVersion = version, Project = projectName}); }
Есть идеи, что я делаю не так? Спасибо!
Ответ №1:
PackageReference
(как и все остальные элементы в файле) находится в пространстве имен XML «http://schemas.microsoft.com/developer/msbuild/2003». Вы должны указать пространство имен в своем вызове, чтобы Descendants
:
XNamespace build = "http://schemas.microsoft.com/developer/msbuild/2003"; var packageReferencesElements = root.Descendants(build "PackageReference");