Count XML Nodes Script Task SSIS - c#

I have the below xml:
<Users>
<User ID="User1"
<Element1>Name1<Element1>
</User>
<User ID="User2"
<Element1>Name2<Element1>
</User>
<User ID="User3"
<Element1>Name3<Element1>
</User>
</Users>
This XML is created and stored in a string variable in SSIS.
I need to count the User nodes before doing the next step and I would like to do it using a script task. This what I think I need to do
// assign string to a variable
String XMLString = Dts.Variables["User::XMLString"].Value
// Convert variable to xml data type:
XmlSerializer serializer = new XmlSerializer(XMLString );
//Count the user nodes and assign integer to a variable.
Dts.Variables["User::UserCount"].Value = serializer.SelectNodes("Users/User").Count;
I’ve been trying to figure out how to do it but I’m quite new on C# and I would really need an example about this please.
Thanks!

You can do this:
string XMLString = Dts.Variables["User::XMLString"].Value;
Dts.Variables["User::UserCount"].Value = (Regex.Matches(XMLString, #"</User>")).Count;
See the code here in this link.

Try this:
XmlDocument doc = new XmlDocument();
doc.Load(XMLString);
Dts.Variables["User::UserCount"].Value = doc.SelectNodes("User").Count;

Related

C# reading an xml file, node value returns as blank

So basically, working on a xml file, that looks like this:
...
<city id="thatstheid">
<country id="anotherid"> VALUE </country>
</city>
...
and i read the stuff i need using:
XmlDocument doc;//let's say this is the file im reading
XmlNode cityNode = doc.DocumentElement.SelectSingleNode("city");
cityname = cityNode.Attributes["id"].Value;
XmlNode countryNode = cityNode.SelectSingleNode("country");
countryname = countryNode.Value;
The problem here being that
countryname = countryNode.Value;
brings back an empty value, even though there's something inside.
If i try to get any atributes from the inside like this :
countryname = countryNode.Attributes["id"].Value;
it works fine, so i don't know what's the problem.
Try InnerText
countryname = countryNode.InnerText;

Extract data from XML using XmlDocument

I am consuming a weather web service in c#. I am passing it Lat-Long and it returns forecasted maximum & minimum temperature of that area. Following is code that i am using
var response = client.ndfdGen(latlong);
XmlDocument doc = new XmlDocument();
doc.LoadXml(response);
And the following is the response data, that I get i.e. xml response
In this response, there is Latitude and Longitude. I have to extract this.
<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<ns1:NDFDgenResponse xmlns:ns1="http://graphical.weather.gov/xml/DWMLgen/wsdl/ndfdXML.wsdl">
<dwmlOut xsi:type="xsd:string"><![CDATA[<?xml version="1.0"?>
<dwml version="1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.nws.noaa.gov/forecasts/xml/DWMLgen/schema/DWML.xsd">
<head>
<product srsName="WGS 1984" concise-name="time-series" operational-mode="official">
<title>NOAA's National Weather Service Forecast Data</title>
<field>meteorological</field>
<category>forecast</category>
<creation-date refresh-frequency="PT1H">2015-04-15T15:13:07Z</creation-date>
</product>
<source>
<more-information>http://www.nws.noaa.gov/forecasts/xml/</more-information>
<production-center>Meteorological Development Laboratory<sub-center>Product Generation Branch</sub-center></production-center>
<disclaimer>http://www.nws.noaa.gov/disclaimer.html</disclaimer>
<credit>http://www.weather.gov/</credit>
<credit-logo>http://www.weather.gov/images/xml_logo.gif</credit-logo>
<feedback>http://www.weather.gov/feedback.php</feedback>
</source>
</head>
<data>
<location>
<location-key>point1</location-key>
<point latitude="39.01" longitude="-77.02"/>
</location>
<moreWeatherInformation applicable-location="point1">http://forecast.weather.gov/MapClick.php?textField1=39.01&textField2=-77.02</moreWeatherInformation>
<time-layout time-coordinate="local" summarization="none">
<layout-key>k-p24h-n2-1</layout-key>
<start-valid-time>2015-04-17T08:00:00-04:00</start-valid-time>
<end-valid-time>2015-04-17T20:00:00-04:00</end-valid-time>
<start-valid-time>2015-04-18T08:00:00-04:00</start-valid-time>
<end-valid-time>2015-04-18T20:00:00-04:00</end-valid-time>
</time-layout>
<parameters applicable-location="point1">
<temperature type="maximum" units="Fahrenheit" time-layout="k-p24h-n2-1">
<name>Daily Maximum Temperature</name>
<value>68</value>
<value>71</value>
</temperature>
</parameters>
</data>
</dwml>]]></dwmlOut>
</ns1:NDFDgenResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
I want to extract information in <time-layout time-coordinate="local" summarization="none"> like start-valid-time,end-valid-time and temperature from <temperature type="maximum" units="Fahrenheit" time-layout="k-p24h-n2-1"> tags.
How can I reach out to these nodes and iterate over it?
You're going to have to extract the CDATA first, that's really the only special challenge here - then you can use XmlDocument or XDocument or XmlReader. I'd recommend doing it this way:
var response = client.ndfdGen(latlong);
XDocument xd = null;
using (XmlReader xr = XmlReader.Create(new StringReader(response))) // load the response into an XmlReader
{
xr.ReadToDescendant("dwmlOut"); // go to the dwmlOut node
xr.Read(); // move to the CDATA in that node
xd = XDocument.Parse(xr.Value); // load **that** XML into your XDocument
}
string startTime = xd.Descendants("start-valid-time").First().Value;
and so on.
If you insist on using XmlDocument, you could use the same method here and just do XmlDocument.LoadFrom(xr.Value), but the XDocument API is a bit more flexible and will certianly perform better.
As suggested in the comments, using XDocument will get you access to a number of LINQ-to-XML methods built for just such a purpose:
// load up the xml into an XDocument
var response = client.ndfdGen(latlong);
var originalDocument = XDocument.Parse(response);
// extract cdata
var cdata = originalDocument.DescendantNodes().OfType<XCData>().First().Value;
var cdataDocument = XDocument.Parse(cdata);
// find the right element via xpath
var myElement = cdataDocument.Root.XPathSelectElement("//dwml/data/location/point");
return myElement.Attribute("latitude").Value;
Note that using the "//" operator in xPath doesn't have great performance. Try nailing down an absolute path once you get the proof of concept working. An explanation of the xPath operations available can be found on MSDN

Append New Element in XML VB or C#

I apologize if this question is too easy for you as I am just starting to learn how XML works. What I am trying to do is to append a new element to App/Library and for example I started with this.
<?xml version="1.0" encoding="utf-8"?>
<App>
<Library>
<Count>100</Count>
<Track>
<TrackID>1</TrackID>
<Name>New York</Name>
<Artist>Snow Patrol</Name>
</Track>
</Library>
</App>
what I am trying to do is to add another track to my existing XML.
<Track>
<TrackID>2</TrackID>
<Name>Chasing Cars</Name>
<Artist>Snow Patrol</Name>
</Track>
There are a couple of ways to deal with xml manipulation in .NET. The older style using System.Xml.XmlDocument or using System.Xml.Linq.XDocument approach.
Here is an example on how to do it using XmlDocument:
var xml = "Baz";
var doc = new XmlDocument();
doc.LoadXml(xml); //Load up the original xml string into XmlDocument object
var fooNode = doc.SelectSingleNode("//foo"); //use xpath to get to the top level foo element
var newBar = doc.CreateElement("bar"); //Create a new bar element and assign it's inner text
newBar.InnerText = "Baz2";
fooNode.AppendChild(newBar); //append the newly created bar element to foo
and here is an example on how to do it using XDocument (which is much more simpler):
var xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><foo><bar>Baz</bar></foo>";
var xdoc = XDocument.Parse(xml); //Load up the original xml string into Linq XDocument object
xdoc.Root.Add(new XElement("bar", "Bar2")); //Add <bar>Bar2</bar> to foo (which is root of the document)
Here is a running example:
https://dotnetfiddle.net/vY7Vag

C# Parsing specific xml

I wonder how do I parse a specific person by the id in the xml below?
Also lets say I wanna loop through them all and add them to a listview, How do I do that with XmlDocument?
<users>
<user id="Marcus">
<website>www.google.com</website>
<type>1</type>
</user>
<user id="John">
<website>www.youtube.com</website>
<type>1</type>
</user>
<user id="Josh">
<website>www.google.com</website>
<type>2</type>
</user>
</users>
Here's a linq to xml example -
using System.Xml.Linq;
var doc = XDocument.Parse(#"...");
var element = doc.XPathSelectElement("/users/user[#id='John']");
var website = element.XPathSelectElement("website").Value;
var type = int.Parse(element.XPathSelectElement("type").Value);

Deleting whole sections of my XML file

I have a userlist for a program I'm designing, and all the users are stored to an XML file, like so:
<?xml version="1.0"?>
<Users>
<User ID="1">
<nickname>Tom</nickname>
<password>Sams</password>
<host>ahost#asd.com</host>
<email>badrandom#as.com</email>
<isloggedin>true</isloggedin>
<permission>10</permission>
</User>
<User ID="2">
<nickname>ohai</nickname>
<password>asdalkdj9u</password>
<host>meh#meh.com</host>
<email>my#email</email>
<isloggedin>false</isloggedin>
<permission>1</permission>
</User>
<User ID="3">
<nickname>ohai</nickname>
<password>sercret</password>
<host>my#host</host>
<email>my#email</email>
<isloggedin>false</isloggedin>
<permission>1</permission>
</User>
<User ID="4">
<nickname>mib_hr6qhr</nickname>
<password>YXNsa2RhZGxrYXNk</password>
<host>adb7e51b#webchat.mibbit.com</host>
<email>alskd#alskd.com</email>
<isloggedin>true</isloggedin>
<permission>1</permission>
</User>
</Users>
Now, based on the users ID number, I need to be able to delete all reference to that user.
So say, I have ID number 3, how can I completely delete userid number 3's existence from the xml file?
I'm looking for code examples, but any help would be greatly appreciated!
One approach using the XML DOM (.NET 1.x and up) would be to just load the file, find user no. 3, and remove that node, and save the file back:
XmlDocument doc = new XmlDocument();
doc.Load("yourXmlFile.xml");
XmlNode userNo3 = doc.SelectSingleNode("//Users/User[#ID='3']");
if(userNo3 != null)
{
userNo3.ParentNode.RemoveChild(userNo3);
}
doc.Save("YourNewXmlFile.xml");
Marc
Assuming you have the XML loaded in an XDocument:
using System.Linq;
using System.Xml.Linq;
void Delete()
{
XDocument document = LoadXML();
document.Elements("Users")
.Single(e => e.Attribute("ID").Value == "3")
.Remove();
}
Of course, this assumes that the user you request will always be present in the XML. To be safe, you should use SingelOrDefault() and check for a null value before deleting.
The problem with linq and DOM approach is that there is a round-trip (parsing/serialization) which can be efficient, vtd-xml has something called incremental update, here is an article that explains it... http://www.codeproject.com/KB/XML/xml_processing_future.aspx
VTDGen vg = new VTDGen();
if (vg.parseFile("your.xml", false)){
VTDNav vn = vg.getNav();
AutoPilot ap = new AutoPilot(vn);
ap.selectXPath("/users/user[#ID='3']");
XMLModifier xm = new XMLModifier(vn);
if (ap.evalXPath()!=-1){
xm.remove();
xm.output("new.xml");
}
}

Categories