XElement creation issue - c#

I'm trying to create a structure like
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="namespace1"
xmlns:image="namespace2">
<url>
<loc>http://www.example.com/foo.html</loc>
<image:image>
<image:loc>http://example.com/image.jpg</image:loc>
</image:image>
</url>
</urlset>
Any ideas on how to create the image elements using XLinq?
Thanks

You're looking for the XNamespace class.
For example:
XNamespace image = "namespace2";
var element = new XElement(image + "image",
new XElement(image + "loc", someUrl)
);

I'm not sure if you can get exactly what your after, but this:
XNamespace ns1 = "namespace1";
XNamespace ns2 = "namespace2";
new XElement(ns1 + "urlset",
new XElement(ns1 + "loc", "http://www.example.com/foo.htm"),
new XElement(ns2 + "image",
new XElement(ns2 + "loc", "http://example.com/image.jpg"))).Dump();
Should get you the equivalent.
<urlset xmlns="namespace1">
<loc>http://www.example.com/foo.htm</loc>
<image xmlns="namespace2">
<loc>http://example.com/image.jpg</loc>
</image>
</urlset>

Related

Dynamic XML depending on List<Object> properties

I'm trying to create and XML Sitemap, and I'm tasked to create it using a List and in a way that if the ImageName property in the List in empty, the XML ignores it but if the property is not empty, it will use the property to build the XML block correctly.
This is what I'm currently using to build the XML:
string imageURL = "https://images.ontheedgebrands.com/images/";
XNamespace xsi = "http://www.w3.org/2001/XMLSchema-instance";
XNamespace gs = "http://www.sitemaps.org/schemas/sitemap/0.9";
XNamespace nsImage = "http://www.google.com/schemas/sitemap-image/1.1";
XDocument doc = new XDocument(
new XElement(gs + "urlset",
new XAttribute("xmlns", gs),
new XAttribute(XNamespace.Xmlns + "image", nsImage),
new XAttribute(XNamespace.Xmlns + "xsi", xsi),
new XAttribute(xsi + "schemaLocation", "http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"),
from rw in rwlist select
new XElement(gs + "url",
new XElement(gs + "loc", site + rw.SEOURL),
new XElement(nsImage + "image",
new XElement(nsImage + "loc", imageURL + rw.ImageName)),
new XElement(gs + "changefreq", "weekly"),
new XElement(gs + "priority", rw.Priority)
)));
doc.Save(file);
And depending on if the rw.ImageName property in in the list and not empty, I want it to build the XML dynamically and look something like this:
<url>
<loc>https://www.budk.com/$10-$20-3231</loc>
<changefreq>weekly</changefreq>
<priority>1.0</priority>
</url>
<url>
<loc>https://www.budk.com/$20-$50-3232</loc>
<changefreq>weekly</changefreq>
<priority>1.0</priority>
</url>
<url>
<loc>https://www.budk.com/-308-Black-Lower-Receiver-Kit--80-Percent-36485</loc>
<image:image>
<image:loc>https://images.ontheedgebrands.com/images/A52-PO2331.jpg</image:loc>
</image:image>
<changefreq>weekly</changefreq>
<priority>1.0</priority>
</url>
<url>
<loc>https://www.budk.com/-40-Cal-Blowgun-Broadhead-Dart-25-Per-Pack-20739</loc>
<image:image>
<image:loc>https://images.ontheedgebrands.com/images/A08-SFBGBHD25.jpg</image:loc>
</image:image>
<changefreq>weekly</changefreq>
<priority>1.0</priority>
</url>
The first two objects in the list had the ImageName property empty and the third and fourth list object had an ImageName so they where build differently.
With the code, right now the XML looks like this, and I don't want the first two XML blocks to add an image attribute because the ImageName property in the List is empty:
<url>
<loc>https://www.budk.com/$10-$20-3231</loc>
<image:image>
<image:loc>https://images.ontheedgebrands.com/images/</image:loc>
</image:image>
<changefreq>weekly</changefreq>
<priority>1.0</priority>
</url>
<url>
<loc>https://www.budk.com/$20-$50-3232</loc>
<image:image>
<image:loc>https://images.ontheedgebrands.com/images/</image:loc>
</image:image>
<changefreq>weekly</changefreq>
<priority>1.0</priority>
</url>
<url>
<loc>https://www.budk.com/-308-Black-Lower-Receiver-Kit--80-Percent-36485</loc>
<image:image>
<image:loc>https://images.ontheedgebrands.com/images/A52-PO2331.jpg</image:loc>
</image:image>
<changefreq>weekly</changefreq>
<priority>1.0</priority>
</url>
<url>
<loc>https://www.budk.com/-40-Cal-Blowgun-Broadhead-Dart-25-Per-Pack-20739</loc>
<image:image>
<image:loc>https://images.ontheedgebrands.com/images/A08-SFBGBHD25.jpg</image:loc>
</image:image>
<changefreq>weekly</changefreq>
<priority>1.0</priority>
</url>
You can use the fact that LINQ to XML ignores null values when adding them. So all you need to do is change this code that unconditionally creates the image element:
new XElement(nsImage + "image",
new XElement(nsImage + "loc", imageURL + rw.ImageName)),
... to this:
string.IsNullOrEmpty(rw.ImageName)
? null
: new XElement(nsImage + "image", new XElement(nsImage + "loc", imageURL + rw.ImageName)),
You could also potentially simplify the code a bit by setting up those XName values beforehand:
XNamespace nsImage = "http://www.google.com/schemas/sitemap-image/1.1";
XName imageXName = nsImage + "image";
XName imageLocXName = nsImage + "loc";
...
// In the argument list
string.IsNullOrEmpty(rw.ImageName)
? null
: new XElement(imageXName, new XElement(imageLocXName, imageURL + rw.ImageName)),

Extract XML attribute values as variables in C# [duplicate]

I am trying to get Absoluteentry tag's value from the below xml string, but its displaying objectrefrence not set exception
<?xml version="1.0" ?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
<env:Body>
<AddResponse xmlns="http://www.sap.com/SBO/DIS">
<PickListParams>
<Absoluteentry>120072</Absoluteentry>
</PickListParams>
</AddResponse>
</env:Body>
</env:Envelope>
Code
XDocument doc = XDocument.Parse(xmlstring);
doc.Element("Envelope").Element("Body").Element("AddResponse").Element("PickListParams").Element("Absoluteentry").Value;
Look at the XML:
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
...
That's the Envelope element in the namespace with URI "http://www.w3.org/2003/05/soap-envelope".
Now look at your code:
doc.Element("Envelope")...
That's looking for an Envelope element that's not in any namespace. You should specify the namespace - and the namespaces of the other elements you're looking for:
XNamespace env = "http://www.w3.org/2003/05/soap-envelope";
XNamespace responseNs = "http://www.sap.com/SBO/DIS";
XDocument doc = XDocument.Parse(xmlstring);
var result = doc.Element(env + "Envelope")
.Element(env + "Body")
.Element(responseNs + "AddResponse")
.Element(responseNs + "PickListParams")
.Element(responseNs + "Absoluteentry").Value;
You can use Descendants too. Descendants finds children at any level.
var result = doc.Element(env + "Envelope")
.Element(env + "Body")
.Descendants(responseNs + "Absoluteentry").Value;

XDocument with multiple namespace in c#

Here is my xml. i am using XDocument in C#. I want to get the "recordSetCount".
<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ShowPositionOpening xmlns="http://data.usajobs.gov">
<ApplicationArea xmlns="http://www.openapplications.org/oagis/9">
<CreationDateTime>2014-12-11T04:05:41</CreationDateTime>
</ApplicationArea>
<DataArea xmlns="http://www.hr-xml.org/3">
<Show recordSetCount="6" recordSetTotal="6" recordSetCompleteIndicator="false" recordSetReferenceId="1" xmlns="http://www.openapplications.org/oagis/9">
<OriginalApplicationArea>
<CreationDateTime>2014-12-11T04:05:41</CreationDateTime>
</OriginalApplicationArea>
</Show>
I have tried like below
var namespaceManager = new XmlNamespaceManager(new NameTable());
namespaceManager.AddNamespace("s", "http://schemas.xmlsoap.org/soap/envelope/");
var jobCount = x.XPathSelectElement("/s:Envelope/s:Body/ShowPositionOpening/DataArea/Show/#recordSetCount", namespaceManager).Value;
but it dint work. Also tried like below
XNamespace xmlns = "http://www.openapplications.org/oagis/9";
XNamespace xmlns1 = "http://data.usajobs.gov";
XNamespace x1 = "http://www.hr-xml.org/3";
var jobCount = x.Element("ShowPositionOpening")
.Element(xmlns1 + "DataArea")
.Element(x1 + "Show")
.Attribute("recordSetTotal");
But it didn't work. What went wrong. Can any one help me?
Your data has multiple namespaces where each child is in a different namespace, you'll need to adjust your queries accordingly.
ShowPositionOpening http://data.usajobs.gov
DataArea http://www.hr-xml.org/3
Show http://www.openapplications.org/oagis/9
var namespaceManager = new XmlNamespaceManager(new NameTable());
namespaceManager.AddNamespace("s", "http://schemas.xmlsoap.org/soap/envelope/");
namespaceManager.AddNamespace("X", "http://data.usajobs.gov");
namespaceManager.AddNamespace("XX", "http://www.hr-xml.org/3");
namespaceManager.AddNamespace("XXX", "http://www.openapplications.org/oagis/9");
// you'll need to change this to XPathEvaluate
// since you're not evaluating to an element
var JobCount = x.XPathEvaluate("/s:Envelope/s:Body/X:ShowPositionOpening/XX:DataArea/XXX:Show/#recordSetCount", namespaceManager);
or using linq:
XNamespace n = "http://data.usajobs.gov";
XNamespace nn = "http://www.hr-xml.org/3";
XNamespace nnn = "http://www.openapplications.org/oagis/9";
var JobCount = x.Descendants(n + "ShowPositionOpening")
.Elements(nn + "DataArea")
.Elements(nnn + "Show")
.Attributes("recordSetCount")
.SingleOrDefault();

Video Sitemap colon in name using LINQ to XML

I am trying to make a video sitemap for video website. But I am facing a XMLExecption "The ':' character, hexadecimal value 0x3A, cannot be included in a name." This is because of colons (video:video) in the name.
XNamespace gs = "http://www.sitemaps.org/schemas/sitemap/0.9";
XDocument doc = new XDocument(
new XElement(gs + "urlset",
(from p in db.Videos
orderby p.video_id descending
select new XElement(gs + "url",
new XElement(gs + "loc", "http://www.example.com/video/" + p.video_id + "-" + p.video_query),
new XElement(gs + "video:video",
new XElement(gs + "video:thumbnail_loc", "http://cdn.example.com/thumb/" + p.video_image)
))).Take(50)));
doc.Save(#"C:\video_sitemap.xml");
Please tell me how to add colons in the name to generate dynamic xml sitemap using LINQ to SQL.
Thanks and Regards.
UPDATE:
This Video XML sitemap should look like on the page:
Google Video Sitemap
video here is the alias for a namespace. As per the example:
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">
<url>
<loc>http://www.example.com/videos/some_video_landing_page.html</loc>
<video:video>
...
</video:video>
</url>
</urlset>
So you just need two XNamespace values - one for the sitemap namespace and one for the video namespace:
XNamespace siteMapNs = "http://www.sitemaps.org/schemas/sitemap/0.9";
XNamespace videoNs = "http://www.google.com/schemas/sitemap-video/1.1";
XDocument doc = new XDocument(
new XElement(siteMapNs + "urlset",
(from p in db.Videos
orderby p.video_id descending
select new XElement(siteMapNs + "url",
new XElement(siteMapNs + "loc",
"http://www.example.com/video/" + p.video_id + "-" + p.video_query),
new XElement(videoNs + "video",
new XElement(videoNs + "thumbnail_loc",
"http://cdn.example.com/thumb/" + p.video_image)
)
)
).Take(50)
)
);
EDIT: If you really want this to use an alias of video for the namespace, you can declare it in your root element:
XDocument doc = new XDocument(
new XElement(siteMapNs + "urlset",
new XAttribute(XNamespace.Xmlns + "video", videoNs),
(from p in db.Videos
...
#Jon Skeet:
Your code generated this sitemap
<?xml version="1.0" encoding="utf-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>http://www.example.com/video/1-video_query_1</loc>
<video xmlns="http://www.google.com/schemas/sitemap-video/1.1">
<thumbnail_loc>http://cdn.example.com/thumb/7665518872558731.jpg</thumbnail_loc>
</video>
</url>
<url>
<loc>http://www.example.com/video/2-video_query_2</loc>
<video xmlns="http://www.google.com/schemas/sitemap-video/1.1">
<thumbnail_loc>http://cdn.jigers.com/thumb/6921835997871337.jpg</thumbnail_loc>
</video>
</url>
but It should be like this:
<?xml version="1.0" encoding="utf-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">
<url>
<loc>http://www.example.com/video/1-video_query_1</loc>
<video:video>
<video:thumbnail_loc>http://cdn.example.com/thumb/7665518872558731.jpg</video:thumbnail_loc>
</video:video>
</url>
<url>
<loc>http://www.example.com/video/2-video_query_2</loc>
<video:video>
<video:thumbnail_loc>http://cdn.jigers.com/thumb/6921835997871337.jpg</video:thumbnail_loc>
</video:video>
</url>
</urlset>
video:video have colons and there should be a xmlns:video="http://www.google.com/schemas/sitemap-video/1.1
namespace in urlset..
Please take a look
You seem to be confusing aliases with namespaces.
Figure out what the namespace for 'videos'. Create an XNamespace for it (like you did in gs).
Then do videoNamespace + "thumbnail_loc".

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")));

Categories

Resources