I have a XML that has a structure similar to this one:
<?xml version="1.0" encoding="UTF-8"?>
<CompanyName>
<AttrContainer>
<Attr type="String">
<Name value="'Name'" />
<Value value="'AttrContainer'" />
</Attr>
<SubContainer>
<AttrContainer value="'WSSMetadata'" />
<AttrContainer>
<Attr type="String">
<Name value="'Name'" />
<Value value="'AttrContainer'" />
</Attr>
<SubContainer>
<WSSMetadata value="'afe2e194-0ce7-4bfc-b446-9623e4fe7189'" />
<AttrContainer>
<Attr type="String">
<Name value="'Name'" />
<Value value="'WSSMetadata'" />
</Attr>
<Attr type="Uuid">
<Name value="'scanID'" />
<Value value="afe2e194-0ce7-4bfc-b446-9623e4fe7189" />
</Attr>
<Attr type="String">
<Name value="'imagePath'" />
</Attr>
<Attr type="String">
<Name value="'imagePathHD'" />
</Attr>
<Attr type="String">
<Name value="'imagePathThumbnail'" />
</Attr>
<Attr type="String">
<Name value="'imagePathGrey'" />
<Value value="'Images/afe2e194-0ce7-4bfc-b446-9623e4fe7189_grey.jpg'" />
</Attr>
<Attr type="String">
<Name value="'imagePathGreyHD'" />
<Value value="'Images/afe2e194-0ce7-4bfc-b446-9623e4fe7189_grey_hd.jpg'" />
</Attr>
<Attr type="String">
<Name value="'imagePathGreyThumbnail'" />
<Value value="'Images/afe2e194-0ce7-4bfc-b446-9623e4fe7189_grey_thumbnail.jpg'" />
</Attr>
</AttrContainer>
</SubContainer>
</AttrContainer>
</SubContainer>
</AttrContainer>
</CompanyName>
and I am trying to parse it using this code (Linq to XML)
var xmlContent = File.ReadAllText(filePathName);
var doc = XDocument.Parse(xmlContent);
var attr = doc.Root.Elements("CompanyName");
var x = attr.ToList();
but it x has no element.
My questions:
What is wrong with this code that I am not able to get the CompanyName element?
How can I get list of all <SubContainer> elements?
When I got the list of <SubContainer> elements, how can I read read and change its content?
I think you want this instead:
var attr = doc.Root.Elements("AttrContainer");
.Elements returns child elements of that name. CompanyName is you root node, and you're trying to search for its children which are AttrContainer.
What is wrong with this code that I am not able to get the companyname element?
The root element of your xml is CompanyName. So what your code is doing, it's essentially asking 'give me all CompanyName elements that are children of my root CompanyName element'. Hence the list is empty.
how can I get list of all SubContainer elements.
You can use
var subContainers = doc.Root.Descendants("SubContainer");
when I got the list of SubContainer elements, how can I read read and change its content?
foreach (var subContainer in subContainers)
{
foreach (var attrContainer in subContainer.Elements("AttrContainer"))
{
var attr = attrContainer.Elements("Attr").FirstOrDefault();
if (attr != null)
{
var oldValue = attr.Attribute("type").Value;
attr.Attribute("type").Value = "something completely different";
}
}
}
This reads and changes the type on each first Attr element (assuming one exists) in all AttrContainers in all SubContainers - hopefully you can derive something meaningful out of that.
doc.Root returns the element <CompanyName>, so further selecting elements named CompanyName won't return any elements. You're effectively trying to select all <CompanyName> elements that are children of <CompanyName>.
This code will select all <SubContainer> elements no matter their depth. I'm suggesting this because your example XML has several <SubContainer> elements.
// Read all Attr elements
IEnumerable<XElement> subContainerElements = doc.Root.Descendants("SubContainer");
foreach (XElement subContainerElement in subContainerElements)
{
// Work with <SubContainer> element here
}
Related
I'm trying to automate the replacement of translations from one XML file to another. The original translator set the translation in the wrong files, and I'm trying to restore them back with an automated process. The original files are like this:
<version major="3" minor="6" revision="3" build="1" />
<region id="TranslatedStringKeys">
<node id="root">
<children>
<node id="TranslatedStringKey">
<attribute id="Content" type="28" handle="ls::TranslatedStringRepository::s_HandleUnknown" value="Spanish 1" />
<attribute id="ExtraData" type="23" value="" />
<attribute id="Speaker" type="22" value="" />
<attribute id="Stub" type="19" value="True" />
<attribute id="UUID" type="22" value="AAA" />
</node>
<node id="TranslatedStringKey">
<attribute id="Content" type="28" handle="ls::TranslatedStringRepository::s_HandleUnknown" value="Spanish 2" />
<attribute id="ExtraData" type="23" value="" />
<attribute id="Speaker" type="22" value="" />
<attribute id="Stub" type="19" value="True" />
<attribute id="UUID" type="22" value="BBB" />
</node>
</children>
</node>
</region>
<content contentuid="h5f6c914fg7db0g4763g9731g58a5eb60c6ab" Source="1.lsb" Key="AAA">English1</content>
<content contentuid="h95735cfdgc22cg4d38g9679ge071f18d77aa" Source="1.lsb" Key="BBB">English2</content>
My goal would be to compare the value of the attribute 'value' in the attribute which id="UUID" to the Key of each 'content' node, and if it is the same then substitute the value of each 'content' node with the value of the attribute 'value' in the attribute which id="Content", so that it ends like:
<content contentuid="h5f6c914fg7db0g4763g9731g58a5eb60c6ab" Source="1.lsb" Key="AAA">Spanish 1</content>
<content contentuid="h95735cfdgc22cg4d38g9679ge071f18d77aa" Source="1.lsb" Key="BBB">Spanish 2</content>
I have tried to operate with C# and Xml.Linq but I have lots of errors in the build of my code since my experience with it is very limited.
Thank you for your help and time
In case someone has the same issue, I found a solution to it:
XmlDocument docMain = new XmlDocument();
XmlDocument docCommon = new XmlDocument();
docMain.Load("spanish.xml");
docCommon.Load("COMMON.xml");
foreach (XmlElement elem in docMain.FirstChild)
{
if (elem.GetAttribute("Key") != "")
{
foreach (XmlElement att in docCommon.SelectNodes("descendant::save/region/node/children/node"))
{
XmlNodeList AttList = (XmlNodeList)att.ChildNodes;
XmlElement trans = (XmlElement) AttList.Item(0);
XmlElement UUID = (XmlElement)AttList.Item(4);
if (elem.GetAttribute("Key") == UUID.GetAttribute("value"))
{
elem.InnerText= trans.GetAttribute("value");
}
else { }
}
}
else { }
}
docMain.Save("modified.xml");
Feel free to add suggestions in order to optimise code if you feel like it.
I have the following XML File:
<order id="1234">
<users>
<user id="102030" nick="nickname" done="false" />
<user id="123456" nick="nickname" done="false" />
</users>
<machines>
<machine id="123" sd="123" ref="" done="false" />
<machine id="456" sd="456" ref="" done="false" />
<machine id="789" sd="789" ref="" done="false" />
</machines>
</order>
I want to delete the user with the id 102030, so the xml looks like this:
<users>
<user id="123456" nick="nickname" done="false" />
</users>
<machines>
<machine id="123" sd="123" ref="" done="false" />
<machine id="456" sd="456" ref="" done="false" />
<machine id="789" sd="789" ref="" done="false" />
</machines>
</order>
This is my code which doesn't work:
XmlDocument doc = XmlDocument.Load(path);
XmlNodeList nodes = doc.GetElementsByTagName("users");
foreach(XmlNode node in nodes){
foreach(XmlAttribute attribute in node.Attributes){
if(attribute.Name== "id" && attribute.Value == "102030"){
node.RemoveAll();
}
}
}
doc.Save(path);
I am a newbie in C# so I need every help!
Thanks in advance, geibi
XmlNode.RemoveAll() does not remove a node. Instead it:
Removes all the child nodes and/or attributes of the current node.
Thus, instead you need to remove the node from its parent:
node.ParentNode.RemoveChild(node);
I am trying to add new attribute to my xml files in c#. my xml file format is shown below:
<Root MessageOfRoot="Welcome to Xml">
<Header Size="36">
<Parameter Name="ID" Index="0" Value="23" />
<Parameter Name="Name" Index="4" Value="Uncle Bob" />
<Parameter Name="Number" Index="8" Value="4" />
</Header>
<Body Size="0">
<Parameter Index="0" UnitNumber="0" Name="UnitBarcode" Type="Integer" />
<Parameter Index="4" PromotionId="0" Name="PromotionalUnit" Type="Integer" />
</Body>
</Root>
I want to add new attribute my xml file which should be like:
<Root MessageOfRoot="Welcome to Xml">
<Header Size="36" NewAttr="1">
<Parameter Name="ID" Index="0" Value="23" NewAttr="1"/>
<Parameter Name="Name" Index="4" Value="Uncle Bob" NewAttr="1"/>
<Parameter Name="Number" Index="8" Value="4" NewAttr="1"/>
</Header>
<Body Size="0" NewAttr="1">
<Parameter Index="0" UnitNumber="0" Name="UnitBarcode" Type="Integer" NewAttr="1"/>
<Parameter Index="4" PromotionId="0" Name="PromotionalUnit" Type="Integer" NewAttr="1"/>
</Body>
</Root>
To do that i write the following code but i am having problem with adding newAttr to all nodes. How can i add NewAttr to my new xml file?
XmlDocument doc = new XmlDocument();
doc.Load("Path of xml");
XmlAttribute NewAttr = doc.CreateAttribute("NewAttr ");
countAttr.Value = "1";
XmlWriter writer = XmlWriter.Create("output.xml", settings);
You can use the following command to load the XML file:
XDocument doc = XDocument.Load(#"C:\Users\myUser\myFile.xml");
Then you can invoke a function that recursively accesses all nodes of the XML starting from the children nodes of the Root element:
AddNewAttribute(doc.Root.Elements());
The function can be like so:
public static void AddNewAttribute(IEnumerable<XElement> elements)
{
foreach (XElement elm in elements)
{
elm.Add(new XAttribute("newAttr", 1));
AddNewAttribute(elm.Elements());
}
}
Finally, you can save the XML back to the original file using:
doc.Save(#"C:\Users\myUser\myFile.xml");
I have an xml file and I want to the write the information on to the csv file.
I am trying to parse the xml to get the fields and the data and write onto a csv file. So far I have been able to parse the data to get the information in relation to
'title' and 'id' under node 'entry' but I am trying to parse the data under node '', 'id' information.
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<feed xml:base="http://google.com/en-US/syndicate/" xmlns:d="http://schemas.google.com/ado/2007/08/dataservices" xmlns:m="http://schemas.giooglt.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
<title type="text">Partners</title>
<id>http://googlre.com/en-US/syndicate/Partners</id>
<updated>2014-01-16T21:33:20Z</updated>
< link rel="self" title="Partners" href="Partners" />
<entry>
<id>http://pinpoint.microsoft.com/en-US/syndicate/Partners('4555')</id>
<title type="text">M55p; Co</title>
<summary type="text">cccc is a Certified Partner, reseller, and implementer of
Key industries we work with include:
• Financial services
• Professional services
• Media / publishing
By focusing on mid-market to enterprise clients,
</summary>
<published>2009-07-21T14:23:50-07:00</published>
<updated>2013-11-22T15:00:46-08:00</updated>
<author>
<name>google chrome</name>
<uri>http://google.com/</uri>
<email>retee#gmail.com</email>
</author>
<link rel="edit" title="Partner" href="Partners('4255')" />
<link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Links" type="application/atom+xml;type=feed" title="Links" href="Partners('4559')/Links">
<m:inline>
<feed>
<title type="text">Links</title>
<id>http://google.com/('429')/Links</id>
<updated>2014-01-16T21:33:20Z</updated>
<link rel="self" title="Links" href="Partners('4ff')/Links" />
<entry>
<id>http://ryryr.com/en-US/syndicate/Links('ufufr')</id>
<title type="text">
</title>
<updated>2014-01-16T21:33:20Z</updated>
<author>
<name />
</author>
<link rel="edit" title="Link" href="Links('partnerpage')" />
<category term="google.Commerce.ferrr.Syndicate.V2010_05.Link" scheme="http://schemas.frrr.com/ado/2007/08/dataservices/scheme" />
<content type="application/xml">
<m:properties>
<d:Type>pgooglrpartnerpage</d:Type>
<d:Description>google Partner Page</d:Description>
<d:Url>http://googlgt.com/en-US/PartnerDetails.aspx?PartnerId=42555&wt.mc_id=66ttet</d:Url>
</m:properties>
</content>
</entry>
</m:inline>
</entry>
<entry>
<id>http://pinpoint.microsoft.com/en-US/syndicate/Partners('4555')</id>
<title type="text">M55p; Co</title>
<summary type="text">cccc is a Certified Partner, reseller, and implementer of
Key industries we work with include:
• Financial services
• Professional services
• Media / publishing
By focusing on mid-market to enterprise clients,
</summary>
<published>2009-07-21T14:23:50-07:00</published>
<updated>2013-11-22T15:00:46-08:00</updated>
<author>
<name>google chrome</name>
<uri>http://google.com/</uri>
<email>retee#gmail.com</email>
</author>
<link rel="edit" title="Partner" href="Partners('4255')" />
<link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Links" type="application/atom+xml;type=feed" title="Links" href="Partners('4559')/Links">
<m:inline>
<feed>
<title type="text">Links</title>
<id>http://google.com/('429')/Links</id>
<updated>2014-01-16T21:33:20Z</updated>
<link rel="self" title="Links" href="Partners('4ff')/Links" />
<entry>
<id>http://ryryr.com/en-US/syndicate/Links('ufufr')</id>
<title type="text">
</title>
<updated>2014-01-16T21:33:20Z</updated>
<author>
<name />
</author>
<link rel="edit" title="Link" href="Links('partnerpage')" />
<category term="google.Commerce.ferrr.Syndicate.V2010_05.Link" scheme="http://schemas.frrr.com/ado/2007/08/dataservices/scheme" />
<content type="application/xml">
<m:properties>
<d:Type>pgooglrpartnerpage</d:Type>
<d:Description>google Partner Page</d:Description>
<d:Url>http://googlgt.com/en-US/PartnerDetails.aspx?PartnerId=42555&wt.mc_id=66ttet</d:Url>
</m:properties>
</content>
</entry>
</m:inline>
</entry>
</feed>
The entries will be different but as one sees, I want to extract the information and write it onto a CSV file as -
Title,Id,PinpointId
//de:entry/de:title,//de:entry/de:title,//de:entry/de:link/m:inline/de:feed/de:id
for each and every entry.
The piece of code being used to get the information is :
// Alternate Method for getting the Fields from the XML file
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load("C:/Users/Administrator/Downloads/direct.xml");
XmlNamespaceManager xmlnm = new XmlNamespaceManager(xmlDocument.NameTable);
xmlnm.AddNamespace("de","http://www.w3.org/2005/Atom");
xmlnm.AddNamespace("m", "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata");
xmlnm.AddNamespace("d", "http://schemas.microsoft.com/ado/2007/08/dataservices");
ParseXML(xmlDocument, xmlnm);
Debug.WriteLine("\n---XML parsed---");
}
public static void ParseXML(XmlDocument xmlFile, XmlNamespaceManager xmlnm)
{
String path = "C:/Users/Administrator/Downloads/data.csv";
var w = new StreamWriter(path);
XmlNodeList nodes = xmlFile.SelectNodes("//de:entry", xmlnm);
foreach (XmlNode node in nodes)
{
string titl = node["title"].InnerText;
string ide = node["id"].InnerText;
//string cty = node["link/m:inline/de:feed/de:id"].InnerText;
Debug.WriteLine("Data :" + titl+"ID :"+ide);
}
}
The output of the program is -
Data :MIG & CoID :http://pinpoint.microsoft.com/en-US/syndicate/Partners('4295719419')
I am trying to parse the data like.
string cty = node["link/m:inline/de:feed/de:id"].InnerText;
But the error generated.
"Object reference not set to an instance of an object."
The xml has got multiple entries and in similar format. New to C# how to get the information and write it on to the CSV file.Please help me.
First, your xml is not well formed. It will need to be corrected. Second, I am unsure exactly what node you are attempting to return with the query "link/m:inline/de:feed/de:id"
With that said, your node["link/m:inline/de:feed/de:id"] isn't valid, so it's not getting set to the XmlNode object you are expecting. That's because an XmlNode item expects the name of a node, not an xpath query. Use SelectSingleNode if you want to pass an xpath query. Something like this:
foreach (XmlNode node in nodes)
{
string titl = node["title"].InnerText;
string ide = node["id"].InnerText;
string cty;
var ctyNode = node.SelectSingleNode("link/m:inline/de:feed/de:id");
if (ctyNode != null)
{
cty = ctyNode.InnerText
}
Debug.WriteLine("Data :" + titl+"ID :"+ide);
}
in my xml file how i can select the value for attributes TagId in ServiceAssignment elements by linq to xml
Note : this xml in a String Property not in xml file
<AnchoredXml xmlns="urn:schema:Microsoft.Rtc.Management.ScopeFramework.2008" SchemaWriteVersion="1">
<Key ScopeClass="Global">
<SchemaId Namespace="urn:schema:Microsoft.Rtc.Management.Settings.ServiceAssignment.2008" ElementName="ServiceAssignments" />
<AuthorityId Class="Host" InstanceId="00000000-0000-0000-0000-000000000000" />
</Key>
<Dictionary Count="1">
<Item>
<Key />
<Value Signature="2ffb6b0d-0239-4016-b08b-40520d1687ff">
<ServiceAssignments xmlns="urn:schema:Microsoft.Rtc.Management.Settings.ServiceAssignment.2008">
<ServiceAssignment TagId="659550892">
<Component Name="Registrar">
<ServiceId xmlns="urn:schema:Microsoft.Rtc.Management.Deploy.Topology.2008" SiteId="1" RoleName="Registrar" Instance="1" />
</Component>
<Component Name="PresenceFocus">
<ServiceId xmlns="urn:schema:Microsoft.Rtc.Management.Deploy.Topology.2008" SiteId="1" RoleName="UserServices" Instance="1" />
</Component>
</ServiceAssignment>
<ServiceAssignment TagId="911048693">
<Component Name="Registrar">
<ServiceId xmlns="urn:schema:Microsoft.Rtc.Management.Deploy.Topology.2008" SiteId="1" RoleName="Registrar" Instance="2" />
</Component>
<Component Name="PresenceFocus">
<ServiceId xmlns="urn:schema:Microsoft.Rtc.Management.Deploy.Topology.2008" SiteId="1" RoleName="UserServices" Instance="2" />
</Component>
</ServiceAssignment>
</ServiceAssignments>
</Value>
</Item>
</Dictionary>
</AnchoredXml>
i try this code but give me a null exception
var MyList = doc.Root.Elements("ServiceAssignment").Select(c=>c.Attribute(("TagId")).Value).ToList();
You have namespaced elements in the document so you need to include them in your queries.
XNamespace itemNs = "urn:schema:Microsoft.Rtc.Management.ScopeFramework.2008";
XNamespace assignmentNs = "urn:schema:Microsoft.Rtc.Management.Settings.ServiceAssignment.2008";
var query =
from item in doc.Descendants(itemNs + "Item")
from assignment in item.Descendants(assignmentNs + "ServiceAssignment")
select (long)assignment.Attribute("TagId");
string xmlString =
#"<AnchoredXml xmlns='urn:schema:Microsoft.Rtc.Management.ScopeFramework.2008' SchemaWriteVersion='1'>
<Key ScopeClass='Global'>
<SchemaId Namespace='urn:schema:Microsoft.Rtc.Management.Settings.ServiceAssignment.2008' ElementName='ServiceAssignments' />
<AuthorityId Class='Host' InstanceId='00000000-0000-0000-0000-000000000000' />
</Key>
<Dictionary Count='1'>
<Item>
<Key />
<Value Signature='2ffb6b0d-0239-4016-b08b-40520d1687ff'>
<ServiceAssignments xmlns='urn:schema:Microsoft.Rtc.Management.Settings.ServiceAssignment.2008'>
<ServiceAssignment TagId='659550892'>
<Component Name='Registrar'>
<ServiceId xmlns='urn:schema:Microsoft.Rtc.Management.Deploy.Topology.2008' SiteId='1' RoleName='Registrar' Instance='1' />
</Component>
<Component Name='PresenceFocus'>
<ServiceId xmlns='urn:schema:Microsoft.Rtc.Management.Deploy.Topology.2008' SiteId='1' RoleName='UserServices' Instance='1' />
</Component>
</ServiceAssignment>
<ServiceAssignment TagId='911048693'>
<Component Name='Registrar'>
<ServiceId xmlns='urn:schema:Microsoft.Rtc.Management.Deploy.Topology.2008' SiteId='1' RoleName='Registrar' Instance='2' />
</Component>
<Component Name='PresenceFocus'>
<ServiceId xmlns='urn:schema:Microsoft.Rtc.Management.Deploy.Topology.2008' SiteId='1' RoleName='UserServices' Instance='2' />
</Component>
</ServiceAssignment>
</ServiceAssignments>
</Value>
</Item>
</Dictionary>
</AnchoredXml>";
var doc = XDocument.Parse(xmlString);
var TagIds = doc.Descendants()
.Elements()
.Where(e =>
e.HasAttributes &&
e.Name.LocalName.Equals("ServiceAssignment") &&
e.Attribute("TagId") != null)
.Select(e => e.Attribute("TagId").Value);
Your XML contains namespaces, so you can't just compare the full name.
If you don't care about the namespaces, you can use XName.LocalName:
var result = from element in doc.Root.Descendants()
where element.Name.LocalName == "ServiceAssignment"
select (int)element.Attribute("TagId");
You can try with this code
var result = from item in XElement.Load("YourFile.xml").Root.Elements("ServiceAssignment")
where item.Attribute("TagId") == value
select item ;