Xdocument parse file and read values - c#

I have the below sample XML , I need to retrive the values for the following two fields txJu and ddate.I also have the code but it is giving null expection
<Doc id="580171" ddate="2019-06-21" >
<ref dtRef="2019-08-21">
<dr>
<cr>
<pj>
<pr>
<dDup txJu="0.00" txFi="0.00" txcOp="0.00" />
<comp txJu="12.96" txFi="2.45" txOp="0.00" />
</pr>
</pj>
</cr>
</dr>
</ref>
</Doc>
var xdoc = XDocument.Load(file);
string txJu = xdoc.Root.Element("comp").Attribute("txJu").Value;
string ddate = xdoc.Root.Element("Doc").Attribute("ddate").Value;

There are a couple of issues with your code. Your Root element doesn't contain comp node, Doc element is root itself, string ddate = string value = ... is invalid C# declaration.
You can modify your code per following
var compElement = xdoc.Root?.DescendantsAndSelf("comp").FirstOrDefault();
string txJu = compElement?.Attribute("txJu")?.Value;
string ddate = xdoc.Root?.Attribute("ddate")?.Value;
string value = ddate;
Use DescendantsAndSelf method to get a collection of filtered comp elements and use first of them. Access ddate attribute directly in Root element. Use null-conditional operator ? to avoid possible null reference exceptions

Related

Selecting a node if the attribute is equal to a predefined string

I'm currently using a loop which gives me a variable, which then needs to be fed into an Xpath method to get me any nodes with an attribute equal to my variable. So far, I've learned that Xpath allows you to select a node from the XML document using
root.SelectNodes("Element[#Attribute='SpecificValue']")
However, I'd like to know if there's a way I can insert a predefined variable where the specific value, so I can grab a different set of nodes with each iteration of my loop.
For example something like this:
string attribValue= "test"
root.SelectNodes("Element[#Attribute = attribValue]")
Use string formatting:
string attribValue = "test";
string expression = String.Format("Element[#Attribute = '{0}']", attribValue);
root.SelectNodes(expression);
Using XML Linq
XDocument doc = new XDocument();
XElement root = (XElement)doc.FirstNode;
string attribValue= "test";
var results = root.Descendants("Element").Where(x => x.Attribute("Attribute").Value == attribValue).ToList();​

Select attribute from xml element

I'm trying to select an attribute from my root node but i keep getting a null exception on the select part.
What's the correct way of getting the value of my attribute?
The value i am trying to get value of the attribute: SymbolicName
The xml document:
<Bundle xmlns="urn:uiosp-bundle-manifest-2.0" Name="ContactUsPlugin" SymbolicName="ContactUsPlugin" Version="1" InitializedState="Active">
<Activator Type="ContactUsPlugin.Activator" Policy="Immediate" />
<Runtime>
<Assembly Path="bin\ContactUsPlugin.dll" Share="false" />
</Runtime>
<Functionality>
<Controller>About</Controller>
<View>Index</View>
</Functionality>
<Scripts>
<Script version="1">
<Location>E:\Git Projects\Kapsters\Plugins\ContactUsPlugin\Sql\Sql1.txt</Location>
</Script>
<Script version="2">
<Location>E:\Git Projects\Kapsters\Plugins\ContactUsPlugin\Sql\Sql1.txt</Location>
</Script>
</Scripts>
</Bundle>
I tried:
string widgetCodeName =
(from db in ManifestDocument.Elements() select db.Attribute("SymbolicName").Value).First();
string widgetCodeName =
(from db in ManifestDocument.Descendants() select db.Element("Bundle").Attribute("SymbolicName").Value).First();
string widgetCodeName =
(from db in ManifestDocument.Element("Bundle").Attributes() where db.Name == "SymbolicName" select db.Value).First();
According to the xml that you have, the bundle tag is the root node. Try:
string widgetCodeName = ManifestDocument.Root.Attribute("SymbolicName").Value;
All this examples work depending on if you need only the value or the XAttribute itself:
XDocument ManifestDocument = XDocument.Load("YourXmlFile.xml");
var myquery = ManifestDocument.Elements().Attributes("SymbolicName").First();//the XAttribute
string myvalue = ManifestDocument.Root.Attribute("SymbolicName").Value;//the value itself
var secondquery = ManifestDocument.Descendants().Attributes("SymbolicName").First();//another way to get the XAttribute
The last one (secondquery) will get SymbolicName attribute even if also defined in another node if you remove the .First().
if this is your entire XML then you can get it with the code below.
XElement elem = XElement.Parse(xmlStr);
string val = elem.Attribute("SymbolicName").Value;
where xmlStr is your XML. if the attribute is missing then the Attribute method will return null so make sure you test for null before accessing the Value property
Your Bundle element has a xml namespace. You need to specify it:
XNamespace ns = "urn:uiosp-bundle-manifest-2.0";
string widgetCodeName = (string)ManifestDocument
.Element(ns + "Bundle")
.Attribute("SymbolicName");
Or, if Bundle is your Root element you can do:
string widgetCodeName = (string)ManifestDocument
.Root
.Attribute("SymbolicName");
Try this :
XNamespace ns = "urn:uiosp-bundle-manifest-2.0";
XDocument xd = XDocument.Load(#"xmlDocument");
var assemblyLocation = from a in xd.Descendants(ns + "Bundle")
select new
{
Path = a.Element(ns + "Runtime").Element(ns + "Assembly").Attribute("Path").Value,
};

LINQ TO XML attribute tag give no object reference error

Hi i am doing as follow
XDocument xmlDoc = XDocument.Load(#"F:\test2.xml");
var q = from c in xmlDoc.Descendants("autoivr.ok")
where c.Element("LS_CZIP4").Value == "1234"
select new
{
name = c.Element("LS_LIN").Value,
state = c.Element("LS_STATE").Value
};
When i use
where c.attribute("LS_CZIP4").Value == "1234"
i get error of object reference not set but when i use c.element there is no such error.
Following is the xml i made which is actually a table in sql converted to xml file
<?xml version="1.0" standalone="yes"?>
<DocumentElement>
<autoivr.ok>
<LS_LIN>abc</LS_LIN>
<LS_STATE>def</LS_STATE>
<LS_TYPE>5</LS_TYPE>
<LS_CZIP4>1234</LS_CZIP4>
<priority>0</priority>
</autoivr.ok>
Can someone let me know the problem and how can i resolve and can i work with element tag only instead of attribute . Thank You
Use casting instead of accessing Value property. Casting to string will return null for non-existing elements. Getting Value will throw an exception
XDocument xmlDoc = XDocument.Load(#"F:\test2.xml");
var q = from c in xmlDoc.Descendants("autoivr.ok")
where (string)c.Element("LS_CZIP4") == "1234"
select new
{
name = (string)c.Element("LS_LIN"),
state = (string)c.Element("LS_STATE")
};
BTW you need closing tag for <DocumentElement>. Also LS_CZIP4 is element, not attribute. See the difference here XML Elements vs. Attributes.
Element: <LS_LIN>abc</LS_LIN>
Attribute: <autoivr.ok LS_LIN="abc">

C# - Issues Selecting XML with Linq

I am trying to pull an event description in XML, but I am having trouble accessing the data.
I am trying to access the eventDetailsValue element.
Here is a sample of my code:
(version 1)
XElement doc = XElement.Parse(e.Result);
evtDesc = doc.Element("eventDetails").Element("eventDetails").Element("eventDetailsValue").Element("eventDetailsValue").Value;
(version2)
XElement doc = XElement.Parse(e.Result);
var xGood = from detaildoc in doc.Descendants("eventDetails")
from d in detaildoc.Elements("eventDetail").Elements("eventDetailsValue")
select d;
I have tried the following for a different element and it worked:
GeoLat = Convert.ToDouble(doc.Element("latitude").Value);
Here is a sample of the xml result (i removed the values for simplicity):
<event>
<longitude></longitude>
<latitude></latitude>
<category></category>
<dma></dma>
<activeAdvantage></activeAdvantage>
<seoUrl></seoUrl>
<assetID></assetID>
<eventID></eventID>
<eventDetailsPageUrl></eventDetailsPageUrl>
- <mediaTypes>
<mediaType></mediaType>
<mediaType></mediaType>
<mediaType></mediaType>
<mediaType></mediaType>
<mediaType></mediaType>
</mediaTypes>
<eventContactEmail />
<eventContactPhone />
<eventName></eventName>
<eventDate></eventDate>
<eventLocation></eventLocation>
<eventAddress></eventAddress>
<eventCity></eventCity>
<eventState></eventState>
<eventZip></eventZip>
<eventCountry></eventCountry>
<usatSanctioned></usatSanctioned>
<regOnline></regOnline>
<eventCloseDate></eventCloseDate>
<currencyCode></currencyCode>
<eventTypeID></eventTypeID>
<eventType></eventType>
<hasEventResults></hasEventResults>
<hasMetaResults></hasMetaResults>
<showMap></showMap>
<eventContactEmail />
<eventContactPhone />
<displayCloseDate></displayCloseDate>
<excludedFromEmailing></excludedFromEmailing>
<regOpensMessage />
<regFunnel></regFunnel>
<isValid></isValid>
<displayRegistration></displayRegistration>
- <channels>
- <channel>
<channelName></channelName>
<primaryChannel></primaryChannel>
</channel>
</channels>
- <eventDetails>
- <eventDetail>
<eventDetailsName></eventDetailsName>
<eventDetailsOrder></eventDetailsOrder>
<eventDetailsValue></eventDetailsValue>
</eventDetail>
- <eventDetail>
<eventDetailsName></eventDetailsName>
<eventDetailsOrder></eventDetailsOrder>
<eventDetailsValue></eventDetailsValue>
</eventDetail>
</eventDetails>
<eventDonationLinks />
<eventSanctions />
- <eventCategories>
- <eventCategory>
<categoryID></categoryID>
<categoryGroupCount></categoryGroupCount>
<categoryName></categoryName>
<categoryType></categoryType>
<categoryOrder></categoryOrder>
<numRegistered></numRegistered>
<maxRegistrations></maxRegistrations>
<percentFull></percentFull>
<displayDate></displayDate>
<closeDate></closeDate>
<actualCloseDate></actualCloseDate>
<isExpired></isExpired>
- <priceChanges>
- <priceChange>
<price></price>
<priceUntilDate></priceUntilDate>
</priceChange>
</priceChanges>
</eventCategory>
</eventCategories>
<eventUrl></eventUrl>
<eventContactUrl></eventContactUrl>
<eventImageUrl></eventImageUrl>
</event>
Any help would be appreciated!
The eventDetailsValue is in an array of eventDetail elements. So you need to diferentiate which element in the array you want. With this (and these LinqToXml extensions: http://searisen.com/xmllib/extensions.wiki) you can write it like this:
XElement doc = XElement.Parse(e.Result);
var details = doc.GetEnumerable("eventDetails/eventDetail", x => new
{
Name = x.Get("eventDetailsName", string.Empty),
Order = x.Get("eventDetailsOrder", string.Empty),
Value = x.Get("eventDetailsValue", string.Empty)
});
details is an IEnumerable<object> of Name's, Order's and the Value(s) you want. You can now loop through details and get the value(s) you want. I made Name, Order and Value all be strings, but by calling Get<type>("name", defaultValueByType) you can have them be other types instead.
You can loop through them like this:
foreach(var detail in details)
{
string value = detail.Value;
}
GetEnumerable is shorthand (in this case) for:
doc.Element("eventDetails").Elements("eventDetail").Select(x => new ...)
But it does null checking for you, which if your xml always produces the above xml, there would be no problems to do it long hand. And Get returns the proper value.
Note: Because this is a WindowsPhone7 project, you'll have to set a compiler flag of WindowsPhone7 so that the extensions compile without complaint (hopefully/I haven't tested it).
Try this query:
var xGood = from detaildoc in doc.Descendants("eventDetails")
select new
{
Value = detaildoc.Elements("eventDetail").Elements("eventDetailsValue").Value
};

How can I parse OWL file (containing RDF namespaces) with LINQ

I managed to parse a simple XML file using LINQ and write it to a list box, but when I tried to get the values from the OWL file I didn't get any result by the query, so the "variables" is empty. Here is one of my attempts to do it:
XDocument owlXML = XDocument.Load(Server.MapPath("App_Data\\filename.owl"));
var variables = from variable in owlXML.Descendants("names")
where variable.Attribute("rdf:ID") != null
select new
{
type = tog.Attribute("rdf:ID").Value
};
ListBox1.DataSource = clothes;
ListBox1.DataBind();
The OWL File
<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
...
...
xml:base="http://www.owl-ontologies.com/Ontology1299428518.owl">
<owl:Ontology rdf:about=""/>
<owl:Class rdf:ID="animal"/>
<owl:Class rdf:ID="natural_disaster">
<rdfs:subClassOf>
<owl:Class rdf:ID="disaster"/>
</rdfs:subClassOf>
<rdfs:subClassOf>
<owl:Class rdf:ID="natural_phenomenon"/>
</rdfs:subClassOf>
</owl:Class>
<names rdf:ID="New York"/>
<names rdf:ID="Washington"/>
<names rdf:ID="Sofia"/>
<names rdf:ID="Miami"/>
</rdf:RDF>
You have to use the appropriate namespace, rdf is not part of the attribute name, it is the namespace it is contained in - you have to declare and use the namespace - for Linq to XML that means using XNamespace - this works:
XDocument owlXML = XDocument.Load("test.xml");
XNamespace rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
var variables = from variable in owlXML.Descendants("names")
where variable.Attribute(rdf +"ID") != null
select new
{
type = variable.Attribute(rdf + "ID").Value
};
Make sure that the value of the namespace in your code matches exactly how it is declared in the XML.
Also since you only have one value you are interested in you do not have to use an anonymous type here, you can simplify by returning a string directly (types then would be IEnumerable<string>):
var types = from variable in owlXML.Descendants("names")
where variable.Attribute(rdf +"ID") != null
select variable.Attribute(rdf + "ID").Value

Categories