简体   繁体   中英

Parsing XML, getting deep elements of specific name. (c#)

I would like to ask you about parsing of XML, I try it by many ways but never get result what I "want/expect". I would like to get ALL elements of specific name ("packageReference") and his attributes/children(elements). After that I will make collection and parse the result to get value of "include" attribute and value of element/atribute with name "version"

example of xml (my elements which I am interest is on bottom):

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup>
        <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
        <IsWebBootstrapper>false</IsWebBootstrapper>
        <PublishUrl>publish\</PublishUrl>
        <Install>true</Install>
        <UpdateIntervalUnits>Days</UpdateIntervalUnits>
    </PropertyGroup>
    <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhoneSimulator' ">
        <DebugSymbols>true</DebugSymbols>
        <DebugType>full</DebugType>
        <Optimize>false</Optimize>
    </PropertyGroup>
    <ItemGroup>
        <Compile Include="Launch.cs" />
        <Compile Include="Launch.designer.cs">
          <DependentUpon>Launch.cs</DependentUpon>
        </Compile>
        <Compile Include="Main.cs" />
        <None Include="Info.plist">
          <SubType>Designer</SubType>
        </None>
    </ItemGroup>
    <ItemGroup>
        <Reference Include="System" />
        <Reference Include="System.Core" />
    </ItemGroup>
    <ItemGroup>
        <ProjectReference Include="..\..\Model\Project.Model.csproj">
          <Project>{0511395F-513C-4F56-BF87-718CA49BB13B}</Project>
          <Name>Project.Model</Name>
        </ProjectReference>
    </ItemGroup>
    <ItemGroup>
        <PackageReference Include="AutoMapper">
          <Version>7.0.1</Version>
        </PackageReference>
        <PackageReference Include="GMImagePicker.Xamarin">
          <Version>2.5.0</Version>
        </PackageReference>
        <PackageReference Include="IdentityModel">
          <Version>4.1.0</Version>
        </PackageReference>
        <PackageReference Include="Microsoft.AppCenter">
          <Version>4.3.0</Version>
        </PackageReference>
        <PackageReference Include="Microsoft.AppCenter.Analytics">
          <Version>4.3.0</Version>
        </PackageReference>
        <PackageReference Include="Microsoft.AppCenter.Crashes">
          <Version>4.3.0</Version>
        </PackageReference>
        <PackageReference Include="Package.Test" Version="1.1.21" />
    </ItemGroup>
  <ItemGroup />
</Project>

The result should be:

AutoMapper;7.0.1
GMImagePicker.Xamarin;2.5.0
...
...
Package.Test;1.1.21

My code:

var text = System.IO.File.ReadAllText(@"C:\MyGit\TestXML3.csproj");
            
var root = XElement.Parse(text);
var packageReferencesElements = root.Descendants("PackageReference");
var packageReferencesElementsAndSelf = root.DescendantsAndSelf("PackageReference");
var packageReferencesElementsOffElement = root.Elements().DescendantsAndSelf("PackageReference");

I tried many ways and few of them you can see in code. I dont want to "go" into every element which have child and checking in loop if there is something what I can be interest. There must be better way. And point there is that I am not sure if my elements which I am looking for is in 2 layer or even deeper.

Update : this code is working to get my information, when I know how deep they are... But when I dont know how deep it should be?

var root = XElement.Parse(fileString);
var itemGroupsELements = root.Elements().Where(x => x.Name.LocalName == "ItemGroup");

var packageReferenceElements = itemGroupsELements.Elements().Where(x => 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});
}

Any idea what I am doing wrong? Thank you!

PackageReference (like all the other elements in the file) is in the XML namespace "http://schemas.microsoft.com/developer/msbuild/2003". You have to specify the namespace in your call to Descendants :

XNamespace build = "http://schemas.microsoft.com/developer/msbuild/2003";
var packageReferencesElements = root.Descendants(build + "PackageReference");

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM