I want to display the first node XML attribute on form? - c#

I have this XML file:
<tree>
<grand name ="tom" id="1" sex="m" status="d" child="2" father="" />
<grand name="adam" id="11" sex="m" status="d" child="1" father="1" />
<grand name="john" id="111" sex="m" status="d" child="1" father="11" />
<grand name="pierre" id="1111" sex="m" status="d" child="3" father="111" />
<grand name="jan" id="11111" sex="f" status="d" child="" father="1111" />
<grand name="marc" id="11112" sex="m" status="d" child="" father="1111" />
</tree>
I try this code to display attribute of the first node only on load the form:
private void Form1_Load(object sender, EventArgs e)
{
XmlDocument XDoc = new XmlDocument();
XDoc.Load("F:\\tree.xml");
XmlNode att = XDoc.SelectSingleNode("//grand/#name");
string nam = att.ToString();
label1.Text = att;
}
But I get nothing.
Thank you very much.

You can do it using linq and XDocument:
XDocument doc = XDocument.Load("F:\\tree.xml");
var result= xdoc.Descendants("grand").First().Attribute("name").Value;
label1.Text = result;
or filter on id attribute this way.
you have to include System.Xml.Linq namespace for it.

Related

XSLT to convert xml into another structure

This is my response structure that i am getting
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<GetPrice_HotelResponse xmlns="PricingAirAPI">
<GetPrice_HotelResult xmlns:a="PricingHotelAPI" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:Error i:nil="true" />
<a:Results xmlns:b="PricingCommonAPI">
<b:HotelSearchResult>
<b:AmountAfterTax>561.9600</b:AmountAfterTax>
<b:AmountBeforeTax>561.9600</b:AmountBeforeTax>
<b:B2B2BHotelPrice xmlns:c="http://schemas.datacontract.org/2004/07/HotelB2B2BPricingEngine">
<c:AgentMarkUp>0</c:AgentMarkUp>
<c:SubAgentMarkUp>0</c:SubAgentMarkUp>
</b:B2B2BHotelPrice>
<b:BookingSource>JacTravel</b:BookingSource>
<b:CityId i:nil="true" />
<b:CityName i:nil="true" />
<b:CountryCode i:nil="true" />
<b:Currency>GBP</b:Currency>
<b:Discount>0.00</b:Discount>
<b:HotelCode>12035</b:HotelCode>
<b:HotelName i:nil="true" />
<b:HotelSupplierResultType>None</b:HotelSupplierResultType>
<b:IsUniversalApiResult>true</b:IsUniversalApiResult>
<b:Price xmlns:c="http://schemas.datacontract.org/2004/07/TekTravel.Hotel.PricingEngine">
<b:AccPriceType>NetFare</b:AccPriceType>
<b:AdditionalTxnFee>0.0</b:AdditionalTxnFee>
<b:AgentCommission>0</b:AgentCommission>
<b:AgentCommissionRate>0</b:AgentCommissionRate>
<b:AgentIncentiveAmt>0.00</b:AgentIncentiveAmt>
<b:AgentIncentiveRate>0.00</b:AgentIncentiveRate>
<b:AgentMarkUp>0</b:AgentMarkUp>
<b:AgentMarkUpAmt>0.0000</b:AgentMarkUpAmt>
<b:AgentMarkUpType>Percentage</b:AgentMarkUpType>
<b:AgentPLB>0</b:AgentPLB>
<b:AgentPLBRate>0</b:AgentPLBRate>
<b:AirlineBaggageCharges>0</b:AirlineBaggageCharges>
<b:AirlineMealCharges>0</b:AirlineMealCharges>
<b:AirlineSeatCharges>0</b:AirlineSeatCharges>
<b:AirlineTransFee>0</b:AirlineTransFee>
<b:CateringCharge>0</b:CateringCharge>
<b:CessTax>0</b:CessTax>
<b:ChargeBU />
<b:CommissionType>RB</b:CommissionType>
<b:ConvenienceCharges>0</b:ConvenienceCharges>
<b:Currency />
<b:CurrencyCode>INR</b:CurrencyCode>
<b:DealId>0</b:DealId>
<b:Discount>0</b:Discount>
<b:EduCessAmount>0</b:EduCessAmount>
<b:EduCessRate>0</b:EduCessRate>
<b:FareBreakdown i:nil="true" />
<b:IsGPEnabled>false</b:IsGPEnabled>
<b:IsOurServiceTaxOnBaseFarePlusYQ>false</b:IsOurServiceTaxOnBaseFarePlusYQ>
<b:IsOurServiceTaxOnComm>false</b:IsOurServiceTaxOnComm>
<b:IsServiceChargeApplicable>true</b:IsServiceChargeApplicable>
<b:IsServiceTaxOnBaseFarePlusYQ>false</b:IsServiceTaxOnBaseFarePlusYQ>
<b:Markup>80</b:Markup>
<b:NetFare>0</b:NetFare>
<b:OtherCharge>0</b:OtherCharge>
<b:OurCommRate>0</b:OurCommRate>
<b:OurCommission>0</b:OurCommission>
<b:OurCommissionType>RB</b:OurCommissionType>
<b:OurEduCessAmt>0</b:OurEduCessAmt>
<b:OurEduCessRate>0</b:OurEduCessRate>
<b:OurIncentiveAmt>0</b:OurIncentiveAmt>
<b:OurIncentiveRate>0</b:OurIncentiveRate>
<b:OurPLB>0</b:OurPLB>
<b:OurPLBRate>0</b:OurPLBRate>
<b:OurPlbType i:nil="true" />
<b:OurServiceTaxAmt>0</b:OurServiceTaxAmt>
<b:OurServiceTaxRate>0</b:OurServiceTaxRate>
<b:OurTdsCommAmt>0</b:OurTdsCommAmt>
<b:OurTdsIncentiveAmt>0.0</b:OurTdsIncentiveAmt>
<b:OurTdsPLBAmt>0</b:OurTdsPLBAmt>
<b:OurTdsRate>0</b:OurTdsRate>
<b:PlbType i:nil="true" />
<b:PrfCurrency i:nil="true" />
<b:PrfROE>0.0</b:PrfROE>
<b:PriceId>0</b:PriceId>
<b:PublishedFare>0</b:PublishedFare>
<b:RateOfExchange>1</b:RateOfExchange>
<b:ResultId>0</b:ResultId>
<b:ReverseHandlingCharge>0</b:ReverseHandlingCharge>
<b:SegmentFee>0</b:SegmentFee>
<b:ServiceTaxRate>0</b:ServiceTaxRate>
<b:SeviceTax>0</b:SeviceTax>
<b:StockType />
<b:SupplierId>0</b:SupplierId>
<b:TDSPLB>0</b:TDSPLB>
<b:Tax>0</b:Tax>
<b:TaxBreakup i:nil="true" xmlns:d="http://schemas.datacontract.org/2004/07/System.Collections.Generic" />
<b:TdsCommission>0</b:TdsCommission>
<b:TdsIncentive>0.00</b:TdsIncentive>
<b:TdsRate>0</b:TdsRate>
<b:TotalGP>0</b:TotalGP>
<b:TransactionFee>0</b:TransactionFee>
<b:WLCharge>0</b:WLCharge>
<b:WLPrice i:nil="true" />
<b:WhiteLabelDiscount>0</b:WhiteLabelDiscount>
<b:YQTax>0</b:YQTax>
<c:DynamicPriceAgentComm>0</c:DynamicPriceAgentComm>
<c:DynamicPriceOurComm>0</c:DynamicPriceOurComm>
</b:Price>
<b:RateType>Negotiated</b:RateType>
<b:RoomDetails />
<b:TotalGP>0</b:TotalGP>
</b:HotelSearchResult>
<b:HotelSearchResult>
.....
</b:HotelSearchResult>
</a:Results>
<a:Status>Successful</a:Status>
<a:TraceId>b748e818-5c6a-4e41-94ca-f8552a328b99</a:TraceId>
</GetPrice_HotelResult>
</GetPrice_HotelResponse>
</s:Body>
</s:Envelope>
Now I want to create xml like
<?xml version="1.0" encoding="utf-16"?>
<ArrayOfHotelSearchResult xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<HotelSearchResult>
<ResultIndex>1</ResultIndex>
<HotelCode>AMB3|LON</HotelCode>
<HotelName>Ambassadors Bloomsbury</HotelName>
<HotelCategory />
<StarRating>FourStar</StarRating>
<HotelDescription>***Special Offer Free welcome gift for stays of 4 or more nights and free bottle of water in each room </HotelDescription>
<HotelPromotion />
<HotelPolicy />
<HotelPicture>http://images.gta-travel.com/HH/Images/GB/LON/LON-AMB3-1.jpg</HotelPicture>
<HotelAddress>12 UPPER WOBURN PLACE London WC1 0HX United Kingdom, , United Kingdom, </HotelAddress>
<HotelContactNo />
<Latitude />
<Longitude />
<AmountBeforeTax>0</AmountBeforeTax>
<AmountAfterTax>0</AmountAfterTax>
<AmountBeforeDiscount>0</AmountBeforeDiscount>
<AmountBeforeTaxInSupplierCurr>259.00</AmountBeforeTaxInSupplierCurr>
<AmountAfterTaxInSupplierCurr>259.00</AmountAfterTaxInSupplierCurr>
<AmountBeforeDiscountInSupplierCurr>259.00</AmountBeforeDiscountInSupplierCurr>
<BookingSource>GTA</BookingSource>
<CurrencySupplier>GBP</CurrencySupplier>
<PreferredROE>0</PreferredROE>
<IsBaseCurrencyRequired>false</IsBaseCurrencyRequired>
<Price>
<CommissionType>RB</CommissionType>
<PlbType>RB</PlbType>
<OurPlbType>RB</OurPlbType>
<AirlineTransFee>0</AirlineTransFee>
<TdsCommission>0</TdsCommission>
<TDSPLB>0</TDSPLB>
<PriceId>0</PriceId>
<PublishedFare>0</PublishedFare>
<NetFare>0</NetFare>
<Markup>0</Markup>
<ServiceTax>0</ServiceTax>
<CessTax>0</CessTax>
<OurCommission>0</OurCommission>
<OurPLB>0</OurPLB>
<AgentCommission>0</AgentCommission>
<AgentPLB>0</AgentPLB>
<OtherCharges>0</OtherCharges>
<Tax>0</Tax>
<WhiteLabelDiscount>0</WhiteLabelDiscount>
<TransactionFee>0</TransactionFee>
<Currency>INR</Currency>
<ChargeBU />
<AccPriceType>PublishedFare</AccPriceType>
<RateOfExchange>0</RateOfExchange>
<AdditionalTxnFee>0</AdditionalTxnFee>
<WLCharge>0</WLCharge>
<Discount>0</Discount>
<ReverseHandlingCharge>0</ReverseHandlingCharge>
<YQTax>0</YQTax>
<IsServiceTaxOnBaseFarePlusYQ>false</IsServiceTaxOnBaseFarePlusYQ>
<TdsRate>0</TdsRate>
<AgentMarkUpType>Percentage</AgentMarkUpType>
<AgentMarkUp>0</AgentMarkUp>
<AgentMarkUpAmt>0</AgentMarkUpAmt>
<ConvenienceCharges>0</ConvenienceCharges>
<PrfROE>0</PrfROE>
<ServiceTaxRate>0</ServiceTaxRate>
<EduCessRate>0</EduCessRate>
<EduCessAmount>0</EduCessAmount>
<AgentCommissionRate>0</AgentCommissionRate>
<AgentPLBRate>0</AgentPLBRate>
<AirlineBaggageCharges>0</AirlineBaggageCharges>
<AirlineMealCharges>0</AirlineMealCharges>
<AirlineSeatCharges>0</AirlineSeatCharges>
<OurCommRate>0</OurCommRate>
<OurPLBRate>0</OurPLBRate>
<OurIncentiveRate>0</OurIncentiveRate>
<OurIncentiveAmt>0</OurIncentiveAmt>
<SegmentFee>0</SegmentFee>
<OurCommissionType>RB</OurCommissionType>
<OurServiceTaxRate>0</OurServiceTaxRate>
<OurServiceTaxAmt>0</OurServiceTaxAmt>
<OurEduCessRate>0</OurEduCessRate>
<OurEduCessAmt>0</OurEduCessAmt>
<OurTdsRate>0</OurTdsRate>
<IsServiceChargeApplicable>true</IsServiceChargeApplicable>
<OurTdsCommAmt>0</OurTdsCommAmt>
<OurTdsPLBAmt>0</OurTdsPLBAmt>
<IsGPEnabled>false</IsGPEnabled>
<TotalGP>0</TotalGP>
<CateringCharge>0</CateringCharge>
<AgentIncentiveRate>0.00</AgentIncentiveRate>
<AgentIncentiveAmt>0.00</AgentIncentiveAmt>
<TdsIncentive>0.00</TdsIncentive>
<DealId>0</DealId>
<SupplierId>0</SupplierId>
<StockType />
<IsPaidByAgentCreditCard>false</IsPaidByAgentCreditCard>
<AmountPaidByAgentCreditCard>0.00</AmountPaidByAgentCreditCard>
<OurTdsIncentiveAmt>0.00</OurTdsIncentiveAmt>
<IsOurServiceTaxOnComm>false</IsOurServiceTaxOnComm>
<IsOurServiceTaxOnBaseFarePlusYQ>false</IsOurServiceTaxOnBaseFarePlusYQ>
<ServiceFee>0</ServiceFee>
<TotalTxnFee>0</TotalTxnFee>
<SwachhBharatCessRate>0</SwachhBharatCessRate>
<SwachhBharatCessAmount>0</SwachhBharatCessAmount>
</Price>
<RateType>Negotiated</RateType>
<CityName />
<IsDomestic>false</IsDomestic>
<NoOfRooms>0</NoOfRooms>
<NoOfNights>0</NoOfNights>
<IsTBOMapped>false</IsTBOMapped>
<SupplierHotelCodes />
<UAPISessionId>7685eeea-c903-4eb7-ae76-2369f40b635c</UAPISessionId>
<HotelDetails>
<StarRating>All</StarRating>
</HotelDetails>
<BookingMode>NotSet</BookingMode>
</HotelSearchResult>
<HotelSearchResult>
.......
</HotelSearchResult>
</ArrayOfHotelSearchResult>
Can anybody help me in making xslt. Currently I an unable to get any value in xslt and i am also facing problem in debugging in VS2012. Sometimes debugger comes sometimes not.
Here is a start using xml linq
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication93
{
class Program
{
const string XML_INPUT = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument inputDoc = XDocument.Load(XML_INPUT);
List<XElement> hotelSearchResults = inputDoc.Descendants().Where(x => x.Name.LocalName == "HotelSearchResult").ToList();
XNamespace aNS = hotelSearchResults[0].GetNamespaceOfPrefix("a");
XNamespace bNS = hotelSearchResults[0].GetNamespaceOfPrefix("b");
string header = "<?xml version=\"1.0\" encoding=\"utf-16\"?>" +
"<ArrayOfHotelSearchResult xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" +
"</ArrayOfHotelSearchResult>";
XDocument doc = XDocument.Parse(header);
XElement arrayOfHotelSearchResult = (XElement)doc.FirstNode;
int count = 0;
foreach (XElement hotelSearchResult in hotelSearchResults)
{
XElement newHotel = new XElement("HotelSearchResult");
arrayOfHotelSearchResult.Add(newHotel);
newHotel.Add(new object[] {
new XElement("ResultIndex", ++count),
new XElement("HotelCode", (string)hotelSearchResult.Descendants(bNS + "HotelCode").FirstOrDefault())
});
XElement price = new XElement("Price");
newHotel.Add(price);
price.Add(new XElement("CommissionType", (string)hotelSearchResult.Descendants(bNS + "CommissionType").FirstOrDefault()));
}
}
}
}
Using XmlReader
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication93
{
class Program
{
const string XML_INPUT = #"c:\temp\test.xml";
static void Main(string[] args)
{
XmlReader reader = XmlReader.Create(XML_INPUT);
XNamespace bNS = "PricingCommonAPI";
while(!reader.EOF)
{
if(reader.Name != "HotelSearchResult")
{
reader.ReadToFollowing("HotelSearchResult", bNS.NamespaceName);
}
if(!reader.EOF)
{
XElement hotelSearchResult = (XElement)XElement.ReadFrom(reader);
}
}
}
}
}
XSLT is a type of stylesheet primarily used to present the data from XML in a human-readable way, usually by putting it into HTML elements.
If you want to convert your existing XML to a new structure, I suggest you use XML tools in C# to deserialize the XML, map it to the new structure and render a new XML.

Edit an element inside cdata

I'm trying to edit an element in the following xml, but I'm not sure how to deal with the cdata code... the element I want to edit is FileID
<Import>
<MethodParameters>
<messageXml><![CDATA[
<Message>
<ImportRequest Entity="Users">
<File Name="XXXXXX" Type="Xml" FileID="TestM-00" TotalPartialFiles="1" PartialSequence="1" Md5="">
<![CDATA[
<ImportUserList>
<ImportUser UserName="TestM01" FirstName="TestM01" MiddleName="TestM01" LastName="TestM01" Active="true" Email="TestM01#gmail.com" ExternalId="TestM01"/>
<ImportUser UserName="TestM02" FirstName="TestM02" MiddleName="TestM02" LastName="TestM02" Active="true" Email="TestM02#gmail.com" ExternalId="TestM02"/>
</ImportUserList>
]]]]><![CDATA[>
</File >
</ImportRequest>
</Message>
]]></messageXml>
</MethodParameters>
</Import>
I have something like this in C#, but I'm not sure how to update the Users.xml file, because I know that AdminNode is in the second document
var doc = new XmlDocument();
doc.Load("E:\\Users.xml");
XmlNode node = doc.SelectSingleNode("/Import/MethodParameters/messageXml").FirstChild;
string newID = Guid.NewGuid().ToString();
XmlNodeList xmlRootNode = doc.GetElementsByTagName("messageXml");
String Sxml = xmlRootNode.Item(0).InnerText;
XmlDocument xdoc = new XmlDocument();
xdoc.LoadXml(Sxml);
XmlNodeList AdminNode = xdoc.GetElementsByTagName("Message");
AdminNode.Item(0).SelectSingleNode("//ImportRequest/File/#FileID").Value = newID;
doc.Save("E:\\Users.xml");
The following code should do the trick:
string xml = #"<Import>
<MethodParameters>
<messageXml><![CDATA[
<Message>
<ImportRequest Entity=""Users"">
<File Name=""XXXXXX"" Type=""Xml"" FileID=""TestM-00"" TotalPartialFiles=""1"" PartialSequence=""1"" Md5="""">
<![CDATA[
<ImportUserList>
<ImportUser UserName=""TestM01"" FirstName=""TestM01"" MiddleName=""TestM01"" LastName=""TestM01"" Active=""true"" Email=""TestM01#gmail.com"" ExternalId=""TestM01""/>
<ImportUser UserName=""TestM02"" FirstName=""TestM02"" MiddleName=""TestM02"" LastName=""TestM02"" Active=""true"" Email=""TestM02#gmail.com"" ExternalId=""TestM02""/>
</ImportUserList>
]]]]><![CDATA[>
</File>
</ImportRequest>
</Message>
]]></messageXml>
</MethodParameters>
</Import>";
var newID = Guid.NewGuid().ToString();
var xDoc = XDocument.Parse(xml);
var messageNode = xDoc.XPathSelectElement(".//messageXml");
var innerDoc = XDocument.Parse(messageNode.Value);
innerDoc.XPathSelectElement(".//ImportRequest/File").Attribute("FileID").Value = newID;
messageNode.ReplaceAll(new XCData(innerDoc.ToString()));
It's pretty dirty now, but at least it produces the expected output:
<Import>
<MethodParameters>
<messageXml><![CDATA[<Message>
<ImportRequest Entity="Users">
<File Name="XXXXXX" Type="Xml" FileID="609bead3-3295-4d68-a07f-1ee47db756fd" TotalPartialFiles="1" PartialSequence="1" Md5="">
<![CDATA[
<ImportUserList>
<ImportUser UserName="TestM01" FirstName="TestM01" MiddleName="TestM01" LastName="TestM01" Active="true" Email="TestM01#gmail.com" ExternalId="TestM01"/>
<ImportUser UserName="TestM02" FirstName="TestM02" MiddleName="TestM02" LastName="TestM02" Active="true" Email="TestM02#gmail.com" ExternalId="TestM02"/>
</ImportUserList>
]]]]><![CDATA[>
</File>
</ImportRequest>
</Message>]]></messageXml>
</MethodParameters>
</Import>

Uncommenting fragment of XML with Xml Document in C#

What is the easiest way of uncommenting the body of some node in XML? The elements have unique name, the structure of the documents look as follows:
somefile.xml
<?xml version="1.0"?>
<name1>
<irrelevant1>
<irrelevant2>
<!--
<irrelevant3 />
-->
</irrelevant2>
</irrelevant1>
<name2>
<name3>
<!--
<name4 field="The" />
<name4 field="Owls" />
<name4 field="Are />
<name4 field="Not" />
<name4 field="What" />
<name4 field="They" />
<name4 field="Seem />
-->
</name3>
</name2>
</name1>
The goal should look like this, with comments removed:
uncommented.xml
<?xml version="1.0"?>
<name1>
<irrelevant1>
<irrelevant2>
<!--
<irrelevant3 />
-->
</irrelevant2>
</irrelevant1>
<name2>
<name3>
<name4 field="The" />
<name4 field="Owls" />
<name4 field="Are />
<name4 field="Not" />
<name4 field="What" />
<name4 field="They" />
<name4 field="Seem />
</name3>
</name2>
</name1>
My approach to parsing:
XmlDocument xdoc = new XmlDocument();
xdoc.Load(#"C:\somefile.xml");
XmlNodeList nl = xdoc.GetElementsByTagName("name2");
XmlNode xn = nl[0];
string xn_content = xn.InnerXml;
xn_content = Regex.Replace(xn_content, "<!--|-->", String.Empty);
XmlDocument doc = new XmlDocument();
doc.LoadXml(xn_content);
XmlNode newNode = doc.DocumentElement;
// this import doesn't really help
xdoc.ImportNode(newNode, true);
xn.RemoveAll();
xn.AppendChild(newNode);
xdoc.Save(#"C:\uncommented.xml");
Results with the ArgumentException:
{"The node to be inserted is from a different document context."}
Your immediate problem is that you call XmlDocument.ImportNode() but do not use the returned node. You need to do newNode = xDoc.ImportNode(newNode, true);.
However, a cleaner way to do this would be to avoid the Regex parsing entirely. Instead, descend the XmlNode hierarchy, pick out the XmlComment nodes you wish to uncomment, load their InnerText into an XmlDocumentFragment, then add its newly created children to the parent node of the comment:
public static class XmlNodeExtensions
{
public static XmlDocument Document(this XmlNode node)
{
for (; node != null; node = node.ParentNode)
{
var doc = node as XmlDocument;
if (doc != null)
return doc;
}
return null;
}
public static IEnumerable<XmlNode> AncestorsAndSelf(this XmlNode node)
{
for (; node != null; node = node.ParentNode)
yield return node;
}
public static IEnumerable<XmlNode> DescendantsAndSelf(this XmlNode root)
{
if (root == null)
yield break;
yield return root;
foreach (var child in root.ChildNodes.Cast<XmlNode>())
foreach (var subChild in child.DescendantsAndSelf())
yield return subChild;
}
public static void UncommentXmlNodes(IEnumerable<XmlComment> comments)
{
foreach (var comment in comments.ToList())
UncommentXmlNode(comment);
}
public static void UncommentXmlNode(XmlComment comment)
{
if (comment == null)
throw new NullReferenceException();
var doc = comment.Document();
if (doc == null)
throw new InvalidOperationException();
var parent = comment.ParentNode;
var innerText = comment.InnerText;
XmlDocumentFragment docFrag = doc.CreateDocumentFragment();
//Set the contents of the document fragment.
docFrag.InnerXml = innerText;
XmlNode insertAfter = comment;
foreach (var child in docFrag.ChildNodes.OfType<XmlElement>().ToList())
{
insertAfter = parent.InsertAfter(child, insertAfter);
}
parent.RemoveChild(comment);
}
}
Then call it like:
string xml = #"<?xml version=""1.0""?>
<name1>
<irrelevant1>
<irrelevant2>
<!--
<irrelevant3 />
-->
</irrelevant2>
</irrelevant1>
<name2>
<name3>
<!--
<name4 field=""The"" />
<name4 field=""Owls"" />
<name4 field=""Are"" />
<name4 field=""Not"" />
<name4 field=""What"" />
<name4 field=""They"" />
<name4 field=""Seem"" />
-->
</name3>
</name2>
</name1>
";
var xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xml);
Debug.WriteLine(xmlDoc.ToXml());
XmlNodeExtensions.UncommentXmlNodes(xmlDoc.DocumentElement.DescendantsAndSelf().OfType<XmlComment>().Where(c => c.ParentNode.Name == "name3"));
Debug.WriteLine(xmlDoc.ToXml());
Note that your commented XML is invalid. <name4 field="Are /> should be <name4 field="Are"/> and <name4 field="Seem /> should be <name4 field="Seem"/>. I fixed that for you in the test case since I assume it's a typo.

Reading in XML from WPF c#

I'm struggling to read in a "GPX" file to a WPF (c#) project. Sample GPX is provided below. I've tried a number of different options with the same result.
Document is loading ok, but I'm unable to break it down to access the Nodes Directly.
Any help would be greatly appreciated.
Thanks.
private void Simple_Click(object sender, RoutedEventArgs e)
{
XmlDocument xml = new XmlDocument();
xml.Load(#"C:\Users\Jonathon\Desktop\GPX_Data.gpx");
XmlNodeList nodes = xml.SelectNodes("trkpt"); // have tried: double '/' to get nodes at any level (XPath syntax)
//XmlNodeList nodes = xml.SelectNodes("/gpx/trk/trkseg/trkpt");
int count = 0;
foreach (XmlNode xn in nodes)
{
count++;
}
}
}
Sample GPX File
<?xml version="1.0" encoding="UTF-8"?>
<gpx version="1.1" creator="Endomondo.com"
xsi:schemaLocation="http://www.topografix.com/GPX/1/1
http://www.topografix.com/GPX/1/1/gpx.xsd
http://www.garmin.com/xmlschemas/GpxExtensions/v3
http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd
http://www.garmin.com/xmlschemas/TrackPointExtension/v1
http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd"
xmlns="http://www.topografix.com/GPX/1/1"
xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1"
xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<metadata>
<author>
<name>Jonathon Ralfe</name>
<email id="jonathon" domain="ralfe.net"/>
</author>
<link href="http://www.endomondo.com">
<text>Endomondo</text>
</link>
<time>2015-01-27T18:31:26Z</time>
</metadata>
<trk>
<src>http://www.endomondo.com/</src>
<link href="https://www.endomondo.com/workouts/463986953/2256850">
<text>endomondo</text>
</link>
<type>SKIING_DOWNHILL</type>
<trkseg>
<trkpt lat="45.576892" lon="6.894079">
<time>2015-01-26T09:49:57Z</time>
</trkpt>
<trkpt lat="45.576892" lon="6.894079">
<ele>1595.0</ele>
<time>2015-01-26T09:49:59Z</time>
</trkpt>
<trkpt lat="45.577109" lon="6.893946">
<ele>1581.0</ele>
<time>2015-01-26T09:51:46Z</time>
</trkpt>
<trkpt lat="45.5772" lon="6.894084">
<ele>1575.0</ele>
<time>2015-01-26T09:52:02Z</time>
</trkpt>
<trkpt lat="45.577247" lon="6.894212">
<ele>1577.0</ele>
<time>2015-01-26T09:52:05Z</time>
</trkpt>
<trkpt lat="45.577317" lon="6.89452">
<ele>1589.0</ele>
<time>2015-01-26T09:52:11Z</time>
</trkpt>
That's because your xml contains namespaces, so you have to set namespace when querying data.
Consider this approach:
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xml.NameTable);
nsmgr.AddNamespace("x", "http://www.topografix.com/GPX/1/1");
XmlNodeList nodes = xml.SelectNodes("//x:trkpt", nsmgr);
Here we're creating NamespaceManager, setting namespace according to your data xmlns="http://www.topografix.com/GPX/1/1" attribute and using this namespace in XPath.
By XPath selection:
foreach(XElement aElement in xml.XPathSelectElements("/trk/trkseg").Elements())
{
foreach(XNode aXNode in aElement.Nodes())
{
//Access subnodes of trkpt
}
}

Insert sibling node into xml document

I have a .net web application that uses XmlDocument to load an XML String. The format of the XML is as follows:
<Sections name="Section Opening Page" PageContentID="201" Template="ReportTags">
<Chapter Name="Introduction" PageContentID="202" Template="ReportTags">
<Pages Name="Why this Document?" PageContentID="203" Template="ReportTags" />
<Pages Name="Target Audience" PageContentID="204" Template="ReportTags" />
</Chapter>
<Chapter Name="Detailed Results" PageContentID="205" Template="ReportTags">
<Pages Name="Question List" PageContentID="206" Template="ReportTags" />
<Pages Name="Answers" PageContentID="207" Template="ReportTags" />
<Pages Name="Comments" PageContentID="208" Template="ReportTags" />
</Chapter>
<Chapter Name="Appendix 1" PageContentID="209" Template="ReportTags">
<Pages Name="Page 1" PageContentID="210" Template="ReportTags" />
<Pages Name="Page 2" PageContentID="211" Template="ReportTags" />
<Pages Name="Page 3" PageContentID="212" Template="ReportTags" />
</Chapter>
<Chapter Name="Appendix 2" PageContentID="213" Template="ReportTags">
<Pages Name="Page 1" PageContentID="214" Template="ReportTags" />
<Pages Name="Page 2" PageContentID="215" Template="ReportTags" />
</Chapter>
</Sections>
As an example, I am trying to insert a NEW NODE under the 'Chapter' named 'Detailed Results' BETWEEN 'Page' named 'Question List' and 'Answers'. The code I am using to do this is as follows:
try
{
string sPath = "Sections/Chapter/Pages[#PageContentID='" + selectedNode.Value + "']";
XmlNode xmlNode = xmlDoc.SelectSingleNode(sPath);
XmlElement xNewChild = xmlDoc.CreateElement("Pages");
xNewChild.SetAttribute("Name", "Another New Page");
xNewChild.SetAttribute("PageContentID", Guid.NewGuid().ToString());
xNewChild.SetAttribute("Template", "ReportTags");
xmlDoc.DocumentElement.InsertAfter(xNewChild, xmlNode);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
However, it is not working, my new node is not inserted into the proper place, it is inserted at the top.
Any help would be greatly appreciated!!
Are you sure that xmlNode is returning the node you think it is? Step through it with the debugger.
If it is null, then the node you insert will get added as a child of the DocumentElement as you describe. If it is returning the Pages node, then you should get an exception 'The reference node is not a child of this node'.
This is fairly self explanatory. The code:
doc.DocumentElement.InsertAfter(xNewChild, xmlNode);
should be:
xmlNode.ParentNode.InsertAfter(xNewChild, xmlNode);
This said, if possible I'd be using XDocument, a part of XLinq. The API's a lot nicer & more powerful, and is generally higher performance. An example:
var element = x.Descendants("Pages").Single(e => e.Attribute("PageContentID").Value == "206");
var newElement = new XElement("Pages",
new XAttribute("Name", "Another New Page"),
new XAttribute("PageContentID", Guid.NewGuid().ToString()),
new XAttribute("Template", "ReportTags"));
element.AddAfterSelf(newElement);
If you don't mind using Linq-To-Xml
XDocument xmlDocument = XDocument.Load("asd.xml");
try
{
var root = xmlDocument.Root;
var pages = root.Elements("Chapter").Elements("Pages");
var mypage = pages.Where(p => p.Attribute("PageContentID").Value == "206").FirstOrDefault();
XElement xNewChild = new XElement("Pages", new XAttribute("Name", "Another New Page"), new XAttribute("PageContentID", Guid.NewGuid().ToString()), new XAttribute("Template", "ReportTags"));
mypage.AddAfterSelf(xNewChild);
xmlDocument.Save("asd.xml");
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
It's const value 206 put in the code, modify to your needs
After execution
"That would probably work, but i am not using Linq for this project. LOL, maybe I should be!!!!!"
So try this, you have to call insertAfter on xmlNode's parent node
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load("asd.xml");
try
{
string sPath = "//Pages[#PageContentID=\"206\"]";
var xmlNode = xmlDocument.SelectSingleNode(sPath);
XmlElement xNewChild = xmlDocument.CreateElement("Pages");
xNewChild.SetAttribute("Name", "Another New Page");
xNewChild.SetAttribute("PageContentID", Guid.NewGuid().ToString());
xNewChild.SetAttribute("Template", "ReportTags");
xmlNode.ParentNode.InsertAfter(xNewChild, xmlNode);
xmlDocument.Save("asd.xml");
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}

Categories

Resources