Getting ItemGroup collection and their Items from MSBuild xml - c#

I want to know the name of the ItemGroup by parsing the below xml in dotnet c#. I tried various options but couldn't get it. Basically i want to know that there are ItemGroup , it can be more. Is there anyway we can load this xml and get the ItemGroups's list and their names.
Here i want the ItemGroup name as "cssfile_individual" , cssfile_individual2
<Project xmlns="http://schemas.microsoft.com/developer/MsBuild/2003">
<UsingTask TaskName="CssCompressorTask" AssemblyFile="Yahoo.Yui.Compressor.Build.MsBuild.dll" />
<UsingTask TaskName="JavaScriptCompressorTask" AssemblyFile="Yahoo.Yui.Compressor.Build.MsBuild.dll" />
<PropertyGroup>
</PropertyGroup>
<Target Name="Minify">
<ItemGroup>
<cssfile_individual Include="test1.css"/>
<cssfile_individual Include="test2.css"/>
<cssfile_individual Include="test3.css"/>
<cssfile_individual Include="test3.css"/>
</ItemGroup>
<ItemGroup>
<cssfile_individual2 Include="test1.css"/>
<cssfile_individual2 Include="test2.css"/>
<cssfile_individual2 Include="test3.css"/>
<cssfile_individual2 Include="test3.css"/>
</ItemGroup>
</Target>
</Project>
I tried as below
XmlDocument objXML = new XmlDocument();
objXML.Load(path);
and then started getting childs and all.
Sample XML looks like this
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/MsBuild/2003">
<UsingTask TaskName="CompressorTask"
AssemblyFile="D:\JsCssCompressor\JsCssCompressor\bin\Yahoo.Yui.Compressor.Build.MsBuild.dll" />
<Target Name="MyTaskTarget">
<ItemGroup>
<JavaScriptFiles Include="C:\Work\Purchase_Flow\eBizSol_App\Release\WebSites\Websites\McAfee.Consumer.Website\UIDesign\LegacySite\Scripts\FlexDashboard\AddDevice.js"/>
</ItemGroup>
<CompressorTask
JavaScriptCompressionType="YuiStockCompression"
JavaScriptFiles="#(JavaScriptFiles)"
ObfuscateJavaScript="True"
PreserveAllSemicolons="False"
DisableOptimizations="Nope"
EncodingType="Default"
DeleteJavaScriptFiles="false"
LineBreakPosition="-1"
JavaScriptOutputFile="C:\Work\Purchase_Flow\eBizSol_App\Release\WebSites\Websites\McAfee.Consumer.Website\UIDesign\LegacySite\Scripts\FlexDashboard\MAA2.0.js"
LoggingType="ALittleBit"
ThreadCulture="en-us"
IsEvalIgnored="false"
/>
</Target>
</Project>

Use LINQ to XML
XDocument objXML = new XDocument();
objXML.Load(path);
Your LINQ code will look something like this
var ItemGroups = from IG in objXML.Descendants("ItemGroup")
select new {
Children = LG.Descendants()
};
//Print Results
string str = "";
foreach (var IG in ItemGroups){
str += "Item Group Name: " + IG.Children[0].Name + Environment.NewLine;
foreach (var IGValue in IG.Children){
str += " " + IGValue.Attribute("Include").Value + Environment.NewLine;
}
}
References
MSDN for LINQ to XML Descendants
LINQ to read XML
Update
Here is a sample application.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace testapp_xdocument_linq
{
class Program
{
static void Main(string[] args)
{
XNamespace ns = "http://schemas.microsoft.com/developer/msbuild/2003";
XDocument X = XDocument.Load("C:\\Users\\Brian\\Documents\\Visual Studio 2012\\Projects\\testapp_xdocument_linq\\testapp_xdocument_linq\\testapp_xdocument_linq.csproj");
var PropertyGroups = from PG in X.Descendants(ns + "PropertyGroup") select PG;
//Print Results
foreach (var element in PropertyGroups)
{
Console.WriteLine("First Descendant Name: " + element.Descendants().First().Name + Environment.NewLine);
}
Console.ReadLine();
}
}
}
This is a fresh C# console app. I am loading the project's own .csproj file.
I am not able to execute this code against your sample XML. I suspect this is because it breaks the schema defined by http://schemas.microsoft.com/developer/msbuild/2003.

You can use Microsoft.Build like this:
var pathToXml = #"<path>";
var nodes = ProjectRootElement.Open(pathToXml).AllChildren;
var itemGroupElements = nodes.OfType<ProjectItemGroupElement>();
And then grab the first child of each Item Group and get its name:
foreach (var itemGroup in itemGroupElements)
{
Console.WriteLine(itemGroup.FirstChild.ElementName);
}

Related

C#: Unhandled exception. System.TypeLoadException: Could not load type 'System.Drawing.Color'

ANSWER for this question thanks to Jeremy C.:
There is no KeePass nuget package for the Net5.0 yet. Thats why there is that error message. Thanks Jeremy C. for the help and answers.
QUESTION:
Im getting this error after starting my solution.
Unhandled exception. System.TypeLoadException: Could not load type 'System.Drawing.Color' from assembly 'Splat, Version=3.0.0.0, Culture=neutral, PublicKeyToken=null'.
Already used google and tried to find a fix for it and also red all articles about similiar errors like "System.Drawing.Font" or "System.Drawing.Image". But theres nothing really helpful and nothing really informative about 'System.Drawing.Color'.
Ive got the code example and package from here:
github.com/wismna/ModernKeePassLib
This is my code:
.csproj
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="ModernKeePassLib" Version="2.45.1" />
<PackageReference Include="System.Drawing.Common" Version="5.0.2" />
</ItemGroup>
</Project>
And:
using ModernKeePassLib;
using ModernKeePassLib.Interfaces;
using ModernKeePassLib.Keys;
using ModernKeePassLib.Serialization;
using System;
using System.Linq;
using System.Text;
namespace KeePasso
{
class Program
{
static void Main()
{
var dbpath = #"C:\Users\prusinma\Desktop\KeePassDatabase\Database.kdbx";
var keypath = #"C:\Users\prusinma\Desktop\KeePassDatabase\Database.key";
var masterpw = "1234abcd";
Console.WriteLine("init done");
byte[] DBPathBytes = Encoding.ASCII.GetBytes(dbpath);
byte[] KeyPathBytes = Encoding.ASCII.GetBytes(keypath);
var ioConnection = IOConnectionInfo.FromByteArray(DBPathBytes);
var compositeKey = new CompositeKey();
compositeKey.AddUserKey(new KcpPassword(masterpw)); // Password
compositeKey.AddUserKey(new KcpKeyFile(IOConnectionInfo.FromByteArray(KeyPathBytes))); // Keyfile
var db = new PwDatabase();
db.Open(ioConnection, compositeKey, new NullStatusLogger());
var kpdata = from entry in db.RootGroup.GetEntries(true)
select new
{
Group = entry.ParentGroup.Name,
Title = entry.Strings.ReadSafe("Title"),
Username = entry.Strings.ReadSafe("UserName"),
Password = entry.Strings.ReadSafe("Password"),
URL = entry.Strings.ReadSafe("URL"),
Notes = entry.Strings.ReadSafe("Notes")
};
db.Save(new NullStatusLogger());
var contents = db.IOConnectionInfo.Bytes;
string bitString = BitConverter.ToString(contents);
Console.WriteLine(bitString);
Console.WriteLine(kpdata.ToString());
}
}
}
Those classes were moved into their own nuget package. Add it to your project and you should be good to go: https://www.nuget.org/packages/System.Drawing.Common/
From the project directory at the command line:
dotnet add package System.Drawing.Common
Closer inspection reveals ModernKeepPass targets.netstandard1.2 and will not work with 5's System.Drawing nuget package without being upgraded to target the new framework.
https://github.com/wismna/ModernKeePassLib/blob/master/ModernKeePassLib/ModernKeePassLib.csproj
<PropertyGroup>
<TargetFramework>netstandard1.2</TargetFramework>

c# Linq XML - Why Is Whitespace Being Added to Elements With Quotes / Namespace?

A portion of my c# .NET program contains code to modify elements within an XML document. The code works fine in terms of modifying the values based on the variables I'm setting elsewhere in the code, but the problem is that whitespace is being added to all of the the elements when the xml file is saved with the updates.
I am not accessing this element at all in my code. I am assuming that it's because of the quotation marks for the algorithm namespace value, because I can't see any other reason why this would happen. I am using Preserve Namespace on load, and Disable Formatting on save.
So question is, why is it adding this extra whitespace, and how can I stop it?
XML (Source File)
<?xml version="1.0" encoding="UTF-8"?>
<PackingList xmlns="http://www.smpte-ra.org/schemas/2067-2/2016/PKL">
<Id>urn:uuid:296a656c-3610-4de1-9b08-2aa63245788d</Id>
<AnnotationText>JOT_Sample</AnnotationText>
<IssueDate>2018-02-16T20:59:42-00:00</IssueDate>
<Issuer>Generic</Issuer>
<Creator>Generic</Creator>
<AssetList>
<Asset>
<Id>urn:uuid:744f36b7-fc7e-4179-8b75-c71c18f98156</Id>
<AnnotationText>Video_744f36b7-fc7e-4179-8b75-c71c18f98156.mxf</AnnotationText>
<Hash>8HhnKnLn+Lp/Ik9i94Ml4SXAxH4=</Hash>
<Size>14568486</Size>
<Type>application/mxf</Type>
<OriginalFileName>Video_744f36b7-fc7e-4179-8b75-c71c18f98156.mxf</OriginalFileName>
<HashAlgorithm Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
</Asset>
<Asset>
<Id>urn:uuid:bf5438ea-ba58-4ae0-a64a-5d23cee2ebb3</Id>
<AnnotationText>Audio_bf5438ea-ba58-4ae0-a64a-5d23cee2ebb3.mxf</AnnotationText>
<Hash>Wg4aEAE5Ji9e14ZyGkvfUUjBwCw=</Hash>
<Size>4341294</Size>
<Type>application/mxf</Type>
<OriginalFileName>Audio_bf5438ea-ba58-4ae0-a64a-5d23cee2ebb3.mxf</OriginalFileName>
<HashAlgorithm Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
</Asset>
</AssetList>
</PackingList>
XML (Output File)
<?xml version="1.0" encoding="UTF-8"?>
<PackingList xmlns="http://www.smpte-ra.org/schemas/2067-2/2016/PKL">
<Id>urn:uuid:296a656c-3610-4de1-9b08-2aa63245788d</Id>
<AnnotationText>JOT_Sample</AnnotationText>
<IssueDate>2018-02-16T20:59:42-00:00</IssueDate>
<Issuer>Generic</Issuer>
<Creator>Generic</Creator>
<AssetList>
<Asset>
<Id>urn:uuid:744f36b7-fc7e-4179-8b75-c71c18f98156</Id>
<AnnotationText>Video_744f36b7-fc7e-4179-8b75-c71c18f98156.mxf</AnnotationText>
<Hash>8HhnKnLn+Lp/Ik9i94Ml4SXAxH4=</Hash>
<Size>14568486</Size>
<Type>application/mxf</Type>
<OriginalFileName>Video_744f36b7-fc7e-4179-8b75-c71c18f98156.mxf</OriginalFileName>
<HashAlgorithm Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
</Asset>
<Asset>
<Id>urn:uuid:bf5438ea-ba58-4ae0-a64a-5d23cee2ebb3</Id>
<AnnotationText>Audio_bf5438ea-ba58-4ae0-a64a-5d23cee2ebb3.mxf</AnnotationText>
<Hash>Wg4aEAE5Ji9e14ZyGkvfUUjBwCw=</Hash>
<Size>4341294</Size>
<Type>application/mxf</Type>
<OriginalFileName>Audio_bf5438ea-ba58-4ae0-a64a-5d23cee2ebb3.mxf</OriginalFileName>
<HashAlgorithm Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
</Asset>
</AssetList>
</PackingList>
Code (partial):
XDocument pkldoc = XDocument.Load(packing, LoadOptions.PreserveWhitespace);
var pklns = pkldoc.Root.GetDefaultNamespace();
var pkluuid = pkldoc.Descendants(pklns + "Id").FirstOrDefault().Value;
var pklassetElements = pkldoc.Descendants(pklns + "Asset");
foreach (var pklasset in pklassetElements)
{
var idElement = pklasset.Descendants(pklns + "Id").First();
if (!idElement.Value.Equals(cpluuid))
continue;
SetNewValue(pklasset, pklns + "OriginalFileName", outfile);
}
void SetNewValue(XElement currentElement, XName elementName, string newValue)
{
var matchingElements = currentElement.Descendants(elementName);
if (matchingElements.Any())
{
foreach (var element in matchingElements)
element.SetValue(newValue);
}
}
pkldoc.Save(packing, SaveOptions.DisableFormatting);
FileInfo fi = new FileInfo(packing);
var pklsize = fi.Length;
This works, though not very clean on my part.
string text = File.ReadAllText(packing);
text = text.Replace(" />", "/>");
File.WriteAllText(packing, text);
UPDATE
This is the solution. Thanks you #asherber !
var textToSave = pkldoc.ToString(SaveOptions.DisableFormatting).Replace(" />", "/>");
File.WriteAllText(packing, textToSave);

How can i get lines of code / fetch declaration in c#? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
Hi can anyone tell me that how can I fetch lines of code from C# code.
For example, I have following code in c#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MyCodeHelp
{
class MultiplicationProgram
{
public int Multiplication(int Firstnumber, int SecondNumber)
{
int Result = (Firstnumber * SecondNumber);
return Result;
}
}
}
So please tell me how can I fetch the following code from the code above and display it in a label or panel?
public int Multiplication(int Firstnumber, int SecondNumber)
{
int Result = (Firstnumber * SecondNumber);
return Result;
}
Get your panel/label name and just do this:
labelName.Text = Result.ToString();
You cannot get the code from the compiled dll, you have to include the code as a resource or as loose files. One way to do this is to add an MSBuild step that causes all Compile items to be embedded as EmbeddedResources.
In your .csproj file, add the below to the end:
Before:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- ... -->
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
After:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- ... -->
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="CodeAsResource" BeforeTargets="BeforeBuild">
<ItemGroup>
<EmbeddedResource Include="#(Compile)" />
</ItemGroup>
</Target>
</Project>
Then you can access it as a resource:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Resources;
using System.Text;
using System.Threading.Tasks;
namespace Codeception
{
class Program
{
static void Main(string[] args)
{
var code = getcode("Program.cs");
Console.WriteLine(code);
}
private static string getcode(string filename)
{
using (var sr = new StreamReader(typeof(Program).Assembly.GetManifestResourceStream("Codeception." + filename)))
{
return sr.ReadToEnd();
}
}
}
}
Here is an example:
private void Form1_Load(object sender, EventArgs e)
{
string filePath = #"";
using (var sr = new StreamReader(filePath))
{
string line;
while ((line = sr.ReadLine()) != null)
{
label1.Text += "\n" + line;
}
}
}
Well, I imagine you want to fetch some lines from the source code you wrote, right?
First of all, you need to ship your code (or a text copy of your code) with your binaries, and put it in a known path.
Then, you can Open the file with File.OpenText method (example in https://msdn.microsoft.com/en-us/library/system.io.file.opentext(v=vs.110).aspx ).
To get specific content from the file (which is the StreamReader you received as return from OpenText method), you can call ReadLine method (example in https://msdn.microsoft.com/en-us/library/system.io.streamreader.readline(v=vs.110).aspx) and search wit String compares (https://msdn.microsoft.com/en-us/library/system.string.compare(v=vs.110).aspx) if you found the piece of code you are looking for.
If you are thinking of changing the code later, I recommend you put the code you would like to share inside a "region" tag (https://msdn.microsoft.com/en-us/library/9a1ybwek.aspx). This way you can look for that region specifically, and you don't need to worry about changing your code.
I hope I could help you.

Retrieve an ancestor attribute

I am attempting to build an external XML config file for several applications, to house their connection strings. The file looks something like this:
<?xml version="1.0" encoding="ISO-8859-1"?>
<configuration>
<Connection Name = "Primary">
<Server Name = "DisneyWorld">
<Database Name ="MagicKingdom">
<Project Name ="Rides">
<Login Username="Mickey" Password="Mouse" Encrypted="False"/>
</Project>
<Project Name = "Food">
<Login Username="Goofy" Password="123456" Encrypted="True"/>
</Project>
<Project Name ="Shows">
<Login Username ="Minnie" Password="Mouse" Encrypted="False"/>
</Project>
</Database>
</Server>
<Server Name = "Epcot">
<Database Name ="LandOfTomorrow">
<Project Name = "Innovation">
<Login Username="Daffy" Password="Duck" Encrypted="False"/>
</Project>
</Database>
</Server>
</Connection>
</configuration>
There will be a secondary connection, in case the primary one is down. What I am wanting to do is search for Project: Food get its log in information, Database and server. Which I can do with this bit of code:
XDocument doc = XDocument.Load(path);
var query = from connection in doc.Descendants("Connection")
where connection.Attribute("Name").Value == "Primary"
from project in connection.Descendants("Project")
where project.Attribute("Name").Value == targetProject
select new
{
Server = connection.Element("Server").Attribute("Name").Value,
Database = project.Parent.Attribute("Name").Value,
UserName = project.Element("Login").Attribute("Username").Value,
Password = project.Element("Login").Attribute("Password").Value,
Encrypted = project.Element("Login").Attribute("Password").Value
};
The code works great, with the exception that it is hard-coded to the current structure.
On the lines
Server = connection.Element("Server").Attribute("Name").Value,
and
Database = project.Parent.Attribute("Name").Value,
I would like to be able to get their values, from project.Ancestors("Server"), but I do understand how to achieve this.
Do you mean something like:
Server = project.Ancestors("Server").Single().Attribute("Name").Value;
Database = project.Ancestors("Database").Single().Attribute("Name").Value;
That's assuming there will only ever be a single ancestor for a given element, of course.

XmlAttributeCollection isn't able to get attributes from xml

I'm using System.Xml to get attributes from my xml file.
It seems that following code which I found somewhere is able to find nodes correctly however it doesn't recognizes attributes (it's weird because I've created this xml files with System.Xml too):
DataSet task_data = new DataSet("Root");
adapter.Fill(task_data); // MySqlDataAdapter is being used here
task_data.WriteXml(path, XmlWriteMode.WriteSchema);
So I don't know why any other xml which can be found on the internet works and mine which was created with the same module doesn't...
using System;
using System.Xml;
using System.IO;
public class Catalog
{
private XmlDocument xmldoc;
private string path = #"C:\Users\Me\Desktop\task.xml";
public static void Main()
{
Catalog c = new Catalog();
}
public Catalog()
//Constructor
{
FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
xmldoc = new XmlDocument();
xmldoc.Load(fs);
DisplayCatalog();
}
// Method for Displaying the catalog
private void DisplayCatalog()
{
XmlNodeList xmlnode = xmldoc.GetElementsByTagName("task");
Console.WriteLine("Here is the list of catalogs\n\n");
for (int i = 0; i < xmlnode.Count; i++)
{
XmlAttributeCollection xmlattrc = xmlnode[i].Attributes; //HERE IS THE PROBLEM!!!
Console.Write(xmlnode[i].FirstChild.Name);
Console.WriteLine(":\t\t" + xmlnode[i].FirstChild.InnerText);
Console.Write(xmlnode[i].LastChild.Name);
Console.WriteLine(":\t" + xmlnode[i].LastChild.InnerText);
Console.WriteLine();
}
Console.WriteLine("Catalog Finished");
}
//end of class
}
This is the xml you linked to contins no attributes only nodes.
<?xml version="1.0" standalone="yes"?>
<Root>
<task>
<TaskId>1</TaskId>
<TaskDelegatorNote>Presentation</TaskDelegatorNote>
<StartTime>PT10H</StartTime>
<EndTime>PT13H</EndTime>
<TaskEndDate>2011-01-02T00:00:00+00:00</TaskEndDate>
<TaskContractorNote>Done</TaskContractorNote>
<TaskStatus>3</TaskStatus>
<LastModification>Me, 2003-05-15 13:48:59</LastModification>
</task>
<task>
<TaskId>2</TaskId>
<TaskDelegatorNote>It must be done.</TaskDelegatorNote>
<StartTime>PT10H</StartTime>
<EndTime>PT13H</EndTime>
<TaskEndDate>2011-01-02T00:00:00+00:00</TaskEndDate>
<TaskContractorNote />
<TaskStatus>2</TaskStatus>
<LastModification>Admin, 2009-08-04 10:30:49</LastModification>
</task>
</Root>
Here's an xml snippint with a TaskId attribute
<task TaskId = 1>
</task>
To fix this change
Console.Write(xmlattrc[0].Name);
Console.WriteLine(":\t\t" + xmlattrc[0].Value);
to
Console.Write(xmlnode[0].ChildNodes[0].Name);
Console.WriteLine(":\t\t" + xmlnode[0].ChildNodes[0].Value);
Your output would be
Here is the list of catalogs
TaskId:
TaskId: 1
LastModification: Me, 2003-05-15 13:48:59
TaskId:
TaskId: 2
LastModification: Admin, 2009-08-04 10:30:49
Catalog Finished
Press any key to continue . . .
Also you should look at LinqToXML for some other ways of doing projections of your xml nodes

Categories