delete a node from sitemap xml - c#

I have sitemap format as below.
I want to delete a complete node that
I find loc.
For example:
Where a node has <loc>with a value of http://www.my.com/en/flight1.
I want to delete the <url> node and his child
I want to delete loc
than lastmod than priority and than changefreq
<url>
<loc>http://www.my.com/en/flight1
</loc>
<lastmod>2015-03-05</lastmod>
<priority>0.5</priority>
<changefreq>never</changefreq>
</url>
<url>
<loc>
http://www.my.com/en/flight2
</loc>
<lastmod>2015-03-05</lastmod>
<priority>0.5</priority>
<changefreq>never</changefreq>
</url>
<url>
<loc>
http://www.my.com/en/flight3
</loc>
<lastmod>2015-03-05</lastmod>
<priority>0.5</priority>
<changefreq>never</changefreq>
</url>

If you're using C# you should use System.xml.linq (XDocument)
You can remove a node like so:
XDocument.Load(/*URI*/);
var elements = document.Root.Elements().Where(e => e.Element("loc") != null && e.Element("loc").Value == "http://www.my.com/en/flight1");
foreach (var url in elements)
{
url.Remove();
}

Related

Xml Root.add value with Special Character( :)

I have an XML file
which is
<?xml version="1.0" encoding="utf-8"?>
<urlset >
</urlset>
I'm trying to add an XElement with special characters (:) code behind
string xmlpath = #"~/myxml.xml";
string path = Server.MapPath(xmlpath);
string title="SomeString"
XDocument doc = XDocument.Load(path);
XElement root = new XElement("url");
root.Add(new XElement("Video:title", "title"));//here is the problem i have Special char (:) which not allowed
doc.Element("urlset").Add(root);
also i can't use &qoute; becuse it's contniue special char & Please i need help if any one can help i would be thankful thanks a lot for your time guys and thank a lot for giving time to read my queation
I'm trying to add an XElement with special characters (:) code behind
Try using a XmlDocument which will allow creating an XmlElement with specified name and namespace.
string xmlpath = #"~/myxml.xml";
string path = Server.MapPath(xmlpath);
XmlDocument doc = new XmlDocument();
doc.Load(path);
var mainRoot = doc.DocumentElement; //urlset element
var urlRoot = doc.CreateElement("url"); //create url element
urlRoot.AppendChild(doc.CreateElement("Video:title","title")); //add element to the url element
mainRoot.AppendChild(urlRoot); // add this new element to the main root of urlset
Example Output:
<?xml version="1.0" encoding="utf-8"?>
<urlset>
<url>
<Video:title xmlns:Video="title" />
</url>
</urlset>
Or if you just want a Video node with namespace of title...
urlRoot.AppendChild(doc.CreateElement("Video","title"));
The output of this above:
<?xml version="1.0" encoding="utf-8"?>
<urlset>
<url>
<Video xmlns="title"/>
</url>
</urlset>
Please let me know if this isn't your expected output.

XMLDocument Access To Last Child

i'm developing sitemap project and have a problem;
this is my xml file
<?xml version="1.0" encoding="UTF-8"?>
<urlset>
<url ID="1">
<loc>http://www.serkancamur.com/Site/Index/sayfa/Hakkimda</loc>
<changefreq>Daily</changefreq>
<priority>0,9</priority>
</url>
</urlset>
this is my c# code:
int ID = Convert.ToInt32(doc.SelectSingleNode("urlset").LastChild.Attributes["ID"].Value);
this works but look to urlset element attributes:
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" schemaLocation="http://www.serkancamur.com/sitemap.xsd">
<url ID="1">
<loc>http://www.serkancamur.com/Site/Index/sayfa/Hakkimda</loc>
<changefreq>Daily</changefreq>
<priority>0,9</priority>
</url>
</urlset>
i only added attributes to urlset element,so why this doesn't work?
You need to use XmlNamespaceManager
Try this
int id = 0;
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("x", "http://www.sitemaps.org/schemas/sitemap/0.9");
var urlset = doc.SelectSingleNode("//x:urlset", nsmgr);
id = Convert.ToInt32(urlset.LastChild.Attributes["ID"].Value);
Hope this helps

Work with XML file

I have a sitemap file for search engines:
<?xml version="1.0" encoding="utf-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
<url>
<loc>http://site.com/</loc>
</url>
<url>
<loc>http://site.com/about</loc>
</url>
<url>
<loc>http://site.com/contacts</loc>
</url>
<url>
<loc>http://site.com/articles/article1.html</loc>
</url>
<url>
<loc>http://site.com/users/123</loc>
</url>
</urlset>
How to insert a new node?
When I use xDoc.Element("url") or xDoc.Element("urlset") or xDoc.Element("xml") or Doc.Elements(...) I get null always. It's very strange.
The code below shows how to navigate within the xml and how to insert a new node
XDocument xDoc = XDocument.Load("sitemap.xml");
XNamespace ns = xDoc.Root.Name.Namespace;
// Navigation within the xml
XElement urlset = xDoc.Element(ns + "urlset");
Console.WriteLine(urlset.Name.LocalName); // -> "urlset"
IEnumerable<XElement> urls = urlset.Elements(ns + "url");
foreach (var url in urls)
{
XElement loc = url.Element(ns + "loc");
Console.WriteLine(loc.Value); // -> "http://site.com/", ...
}
// Inserting a new node under "urlset" node
urlset.Add(
new XElement(ns + "url",
new XElement(ns + "loc",
"http://site.com//questions/4183526")));

Issues querying google sitemap.xml with Linq to XML

I have a Linq-2-XML query that will not work if a google sitemap that I have created has its urlset element populated with attributes but will work fine if there are no attributes present.
Can't query:
<?xml version="1.0" encoding="utf-8"?>
<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9
http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"
xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>http://www.foo.com/index.htm</loc>
<lastmod>2010-05-11</lastmod>
<changefreq>monthly</changefreq>
<priority>1.0</priority>
</url>
<url>
<loc>http://www.foo.com/about.htm</loc>
<lastmod>2010-05-11</lastmod>
<changefreq>monthly</changefreq>
<priority>1.0</priority>
</url>
</urlset>
Can query:
<?xml version="1.0" encoding="utf-8"?>
<urlset>
<url>
<loc>http://www.foo.com/index.htm</loc>
<lastmod>2010-05-11</lastmod>
<changefreq>monthly</changefreq>
<priority>1.0</priority>
</url>
<url>
<loc>http://www.foo.com/about.htm</loc>
<lastmod>2010-05-11</lastmod>
<changefreq>monthly</changefreq>
<priority>1.0</priority>
</url>
</urlset>
The query:
XDocument xDoc = XDocument.Load(#"C:\Test\sitemap.xml");
var sitemapUrls = (from l in xDoc.Descendants("url")
select l.Element("loc").Value);
foreach (var item in sitemapUrls)
{
Console.WriteLine(item.ToString());
}
What would be the reason for this?
See the "xmlns=" tag in the XML? You need to specify the namespace. Test the following modification of your code:
XDocument xDoc = XDocument.Load(#"C:\Test\sitemap.xml");
XNamespace ns = "http://www.sitemaps.org/schemas/sitemap/0.9";
var sitemapUrls = (from l in xDoc.Descendants(ns + "url")
select l.Element(ns + "loc").Value);
foreach (var item in sitemapUrls)
{
Console.WriteLine(item.ToString());
}

C# extension where method - handling a case when element not found

I am trying to query this very complicated XML document using xDocument and LINQ to XML. I want to perform the following action:
Get all elements that answer to a certain criteria, and if they don't, return another attribute from the xDocument.
Example:
<cars>
<car>
<patrol type="oil">
<url> http://Toyotaoil.com </url>
</patrol>
</car>
<car>
<patrol type="oil">
<url> http://BMWoil.com </url>
</patrol>
<patrol type="gas">
<url> http://BMWgas.com </url>
</patrol>
</car>
<car>
<patrol type="gas">
<url> http://Hondagas.com </url>
</patrol>
</car>
Now what I'd like to get from this query is a list of patrols of type oil, unless the car doesn't use petrol, and then I'd be satisfied with gas.
If I use the where clause I just miss the cases where the car uses gas. Is there any such thing like a where clause, where I can specify what to do if they condition wasn't met?
The solution below should give you the flexibility to query whatever you like:
var result = from car in xdoc.Element("cars").Elements("car")
let patrols = car.Elements("patrol")
let oils = patrols.Where(patrol => patrol.Attribute("type") == "oil")
select new {
Car = car,
Patrols = (oils.Any() ? oils : patrols)
}
I don't have Visual Studio here, so I hope it compiles :)
Give a bit more information on what you like to select, and I'll give you a more specific LINQ statement.
xdoc.Element("cars")
.Elements("car")
.Select(car => car.Elements("patrol")
.SingleOrDefault(p => (string)p.Attribute("type") == "oil")
??
car.Elements("patrol")
.Single(p => (string)p.Attribute("type") == "gas"));
You can just make something like this:
var query = from element in someElements
select element.Attribute("type").Value == "oil"
? returnSomethingWhenItIsOil
: returnSomethingWhenItIsSomethingElse;
or
var query = from element in someElements
where element.Attribute("type") == "oil"
|| element.Attribute("type") == "gas"
select element;
But explain the problem better, thanks :)
It sounds like you don't actually want a where clause at all - you just want a select clause that either picks one value or another.
However, your example doesn't really describe how you'd select a different item based on the values - which "other attribute" would you select? What do you mean by "where the car uses gas"? If you can give more details of the example, it shouldn't be too hard to give you matching code.
var cars = from c in xdoc.Descendants("car")
where
(c.Element("patrol").Attribute("type").Value == "oil" ||
c.Element("patrol").Attribute("type").Value == "gas")
select new Car
{
FuelType = c.Element("patrol").Attribute("type").Value.ToString()
};
foreach (Car c in cars)
{
Console.WriteLine(c.ToString());
}
class Car
{
public string FuelType { get; set; }
public override string ToString()
{
return "Car FeulType = " + this.FuelType.ToString();
}
}
These are the results, I am getting
alt text http://img694.imageshack.us/img694/5016/carse.jpg
Order by type according to your specifications, take FirstOrDefault().
Edit: What I meant was something like this:
var patrols = from car in doc.Root.Elements()
let p = car.Elements().OrderBy(patrol=>patrol.Attribute("type").Value).First()
select p;
This returns one result per car. Check the OrderBy clause and adjust it accordingly. This would result in:
<patrol type="oil">
<url> http://Toyotaoil.com </url>
</patrol>
<patrol type="gas">
<url> http://BMWgas.com </url>
</patrol>
<patrol type="gas">
<url> http://Hondagas.com </url>
</patrol>
Edit again: Ah, now it clicked. Yes, this only returns a single item per car - Zyphrax gave a nice solution.

Categories

Resources