C# sql query to add attributes for the elements in xml - c#

I want to display the XML file by taking tag from the XML_TAGS table, and attributes from theMAPPED_TAGS_ATTRIBUTES table - something like <element attributes></element>:
String sql = "SELECT Dtd_Tag,Dtd_Attribute_Name
FROM Xml_Tags,
Mapped_Tags_Attributes
WHERE Mapped_Tags_Attributes.Pdf_Tag = Xml_Tags.Pdf_Tag
ORDER BY Mapped_Tags_Attributes.Pdf_Tag
FOR XML AUTO";

Query:
select
c.CustomerId as "#Id",
c.AcountNumber as "#AcountNumber"
from Customer c
for xml path('Customer'), root('Customers')
Result:
<Customers>
<Customer Id="1" AccountNumber="X120" />
<Customer Id="2" AccountNumber="X121" />
</Customers>

Related

Dynamically Creating LINQ Query to query XML Elements

I have an XML similar to below,
<?xml version="1.0" encoding="utf-8"?>
<body>
<Result>
<Students>
<Student>
<Firstname Value="Max" />
<LastName Value="Dean" />
</Student>
<Student>
<Firstname Value="Driz" />
<LastName Value="Jay" />
</Student>
</Students>
</Result>
</body>
I'm trying to figure out if its possible to write some code to dynamically build a Linq query from something like,
string pathToElements = "Result.Students.Student";
var individualItems = pathToElements.Split(".");
to something like,
XElement document = XElement.Parse(xml);
var evaluatedResult = document.Elements("Result")
.Elements("Students")
.Elements("Student")
.ToList();
basically the individualItems has 3 items "Result", "Students" and "Student". I'm exploring possible ways to create a dynamic query to accomplish something like,
document.Elements("Result")
.Elements("Students")
.Elements("Student")
.ToList();
For n number of Items I would just need to keep appending .Elements("") to the query.
Any advice on how to achieve this, my first instinct was to use a string builder and have the query as a string. I was able to do this but was not able to find out how a LINQ query which is in the form of a string can be executed.
Thanks in advance
You can query XML using XPath (it's a string so you can create it dynamically) then you can deserialize the item
https://learn.microsoft.com/en-us/troubleshoot/developer/dotnet/framework/general/query-xpathdocument-xpath-csharp
The output of this code
using System;
using System.Xml.XPath;
using System.IO;
public class Program
{
public static void Main()
{
var xml = #"<?xml version=""1.0"" encoding=""utf-8""?>
<body>
<Result>
<Students>
<Student>
<Firstname Value=""Max"" />
<LastName Value=""Dean"" />
</Student>
<Student>
<Firstname Value=""Driz"" />
<LastName Value=""Jay"" />
</Student>
</Students>
</Result>
</body>";
using (TextReader tr = new StringReader(xml))
{
var xdoc = new XPathDocument(tr);
var nav = xdoc.CreateNavigator();
var nodeIter = nav.Select("/body/Result/Students/Student");
while (nodeIter.MoveNext())
{
Console.WriteLine("Student: {0}", nodeIter.Current.InnerXml);
};
}
}
}
is
Student: <Firstname Value="Max" />
<LastName Value="Dean" />
Student: <Firstname Value="Driz" />
<LastName Value="Jay" />

Get XML attribute Values by its Descendants

I have an XML in this Format and I want to get List of Line ID and its Name
<ArrayOfLines xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<LineStatus ID="0" StatusDetails="">
<BranchDisruptions />
<Line ID="1" Name="Line1" />
<Status ID="GS" CssClass="GoodService" Description="Good Service" IsActive="true">
<StatusType ID="1" Description="Line" />
</Status>
</LineStatus>
<LineStatus ID="1" StatusDetails="">
<BranchDisruptions />
<Line ID="2" Name="Line2" />
<Status ID="GS" CssClass="GoodService" Description="Good Service" IsActive="true">
<StatusType ID="1" Description="Line" />
</Status>
</LineStatus>
</ArrayOfLines>
and This is the code I have written:
String xmlFilePath = #"C:/myXML.xml";
XDocument xmlFile = XDocument.Load(xmlFilePath);
var query = from c in xmlFile.Descendants("LineStatus") select c;
but it is not returning me any results.
Here is my idea but you have to create list "namesList" and "idList" before. Try this:
XDocument xDoc = XDocument.Load("your xml file");
foreach (var elem in xDoc.Document.Descendants("line"))
{
idList.Add(elem.Attribute("ID").Value);
namesList.Add(elem.Attribute("Name").Value);
}
And you have full controll by index of each list to this data. After that you can also create object of these 2 elements
You have an xml namespace, you need to specify it with element names:
XNamespace ns = "http://www.w3.org/2001/XMLSchema-instance";
var query = from c in xmlFile.Descendants(ns + "LineStatus") select c;
Try this...
String xmlFilePath = #"C:/myXML.xml";
XDocument xmlFile = XDocument.Load(xmlFilePath);
var query = (from c in xmlFile.Descendants("Line")
select new {
ID=c.Attribute("ID").Value,
Name=c.Attribute("Name").Value
}).ToList();;

Replacing Some Elements in XML [Sample XML Provided]

I have an xml document that looks like this.I have a XML file structured as below.
Sample XML is as follows:
<Dr.Watson>
<Bugs>
<Bug Name="Bug.add --> AAAAAAAAAAAA">
<criteria>
<includeFilterSets>
<filterSet>
<filter>
<filterName>PRODUCT_NAME</filterName>
<operator>
<name>Equals</name>
</operator>
<value>Dr.Watson</value>
</filter>
</filterSet>
</includeFilterSets>
<grouping>
<groupBy>
<name>STATUS</name>
</groupBy>
</grouping>
<caseSensitive>false</caseSensitive>
<entityToSearch>
<name>BUG</name>
</entityToSearch>
</criteria>
</Bug>
</Bugs>
</Dr.Watson>
I want to replace some of elements in the XML file like below:
<Dr.Watson>
<Bugs>
<Bug Name="Bug.add --> AAAAAAAAAAAA">
<criteria>
<includeFilterSets>
<filterSet>
<filter>
<filterName>PRODUCT_NAME</filterName>
<operator>
<name>Equals</name>
</operator>
<value>Dr.Watson</value>
</filter>
</filterSet>
</includeFilterSets>
<grouping>
<groupBy>
<name>STATE</name>
</groupBy>
</grouping>
<caseSensitive>false</caseSensitive>
<entityToSearch>
<name>BUG</name>
</entityToSearch>
</criteria>
</Bug>
</Bugs>
</Dr.Watson>
i would like to change the available under followed by as State.
Please suggest.
var xdoc = XDocument.Load(path_to_xml);
var groupByName = xdoc.XPathSelectElement("//groupBy/name");
groupByName.Value = "STATE";
xdoc.Save(path_to_xml);

Linq to XML Add element to specific sub tree

My XML:
<Bank>
<Customer id="0">
<Accounts>
<Account id="0" />
<Account id="1" />
</Accounts>
</Customer>
<Customer id="1">
<Accounts>
<Account id="0" />
</Accounts>
</Customer>
<Customer id="2">
<Accounts>
<Account id="0" />
</Accounts>
</Customer>
</Bank>
I want to add new Account element to lets say Customer with id 2. I know how to add the line what I dont know how do I specify the customer (where do I write the Customer's ID ?)
My LINQ to XML code:
XDocument document = XDocument.Load("database.xml");
document.Element("Bank").Element("Customer").Element("Accounts").Add
(
new XElement
(
"Account", new XAttribute("id", "variable")
)
);
document.Save("database.xml");
Thanks for the help. XML is not my good friend :(
You are almost there, your code will be default add the element to the first Customer. You need to search for the attribute id in collection of Customers whose value is 2 -
document.Element("Bank").Elements("Customer")
.First(c => (int)c.Attribute("id") == 2).Element("Accounts").Add
(
new XElement
(
"Account", new XAttribute("id", "variable")
)
);
I know how to add the line what I dont know how do I specify the customer (where do I write the Customer's ID ?)
You need to find the Customer element with the right ID first. For example:
var customer = document.Root
.Elements("Customer")
.Single(x => (int) x.Attribute("id") == id);
customer.Element("Accounts").Add(new XElement("Account",
new XAttribute("id", "variable")));
Note that this will fail on the Single call if there isn't exactly one Customer element with the right ID. If you want to create a new customer, you'll need to do a bit more work - but presumably that would be in a different call anyway.
var cust = xDoc.Descendants("Customer")
.First(c => c.Attribute("id").Value == "2");
cust.Element("Accounts").Add(new XElement("Account", new XAttribute("id","3") ));

XML DataGrid Where Certain Nodes Are Empty

I am attempting to bind an XML file to a DataGrid. I am only bind the the "Transactions". What I cannot figure out is how to bind only data that has empty nodes. For example, the transaction that has "UserName" of "NSmith" does not have a value for "CustomerFirst".
I want only this child to be bound to the DataGrid
<Root>
<Header>
<value1>0000000</value1>
<value2>1</value2>
<value3>100.00</value3>
</Header>
<Transactions>
<Txn>
<id></id>
<UserName>BSmith</User>
<CustomerFirst>Bob</CustomerFirst>
...
</Txn>
<Txn>
<id></id>
<UserName>NSmith</User>
<CustomerFirst></CustomerFirst>
...
</Txn>
</Transactions>
</Root>
Here is my C# code:
serverPath = Server.MapPath("App_Data/" + xmlFileName);
DataSet dsBillPay = new DataSet();
dsBillPay.ReadXml(serverPath);
dgBillPay.DataSource = dsBillPay.Tables[1];
dgBillPay.DataBind();
The .Tables[1] is selecting the "Transactions".
Now the question is selecting data that has empty nodes.
Thank you in advance.
You can use Linq-to-Xml to filter out elements that have all of their child-elements specified with values and include only those with missing data.
The following example retrieves users that have an empty element but allows AddressTwo to be empty.
string xmlText = #"<Root>
<Header>
<value1>0000000</value1>
<value2>1</value2>
<value3>100.00</value3>
</Header>
<Transactions>
<Txn>
<id>1</id>
<UserName>BSmith</UserName>
<CustomerFirst>Bob</CustomerFirst>
</Txn>
<Txn>
<id>2</id>
<UserName>NSmith</UserName>
<CustomerFirst></CustomerFirst>
</Txn>
<Txn>
<id></id>
<UserName>JSmith</UserName>
<CustomerFirst>James</CustomerFirst>
</Txn>
<Txn>
<id>4</id>
<UserName>KSmith</UserName>
<CustomerFirst>Kevin</CustomerFirst>
<AddressTwo></AddressTwo>
</Txn>
</Transactions>
</Root>";
var root = XElement.Parse(xmlText);
var elementsThatCanBeEmpty = new HashSet<XName>
{
XName.Get("AddressTwo")
};
var transactionsWithoutCustomerFirst =
from transactions in root.Elements(XName.Get("Transactions")).Elements()
where transactions.Elements().Any
(
el =>
String.IsNullOrEmpty(el.Value) &&
!elementsThatCanBeEmpty.Contains(el.Name)
)
select transactions;
foreach(var t in transactionsWithoutCustomerFirst)
{
Console.WriteLine(t.Element(XName.Get("UserName")).Value);
}

Categories

Resources