The following Unit Test passes in VB.Net
<Test()> _
Public Sub VB_XMLLiteral_SyntaxRocks_Test()
Dim XML = <Doc>
<Level1>
<Item id="1"/>
<Item id="2"/>
</Level1>
<Level1>
<Item id="3"/>
<Item id="4"/>
</Level1>
</Doc>
Assert.AreEqual(4, XML.<Level1>.<Item>.Count)
End Sub
How do I assert the same thing in C#?
To clarify, I 'd like to know how to express...
XML.<Level1>.<Item>
...in C#
Assert.AreEqual(4, XML.Elements("Level1").Elements("Item").Count());
And of course XML needs to be an XElement (that's what a VB literal produces too)
Using LINQ to XML:
var XML = new XElement("Doc",
new XElement("Level1",
new XElement("Item",
new XAttribute("Id", 1)),
new XElement("Item",
new XAttribute("Id", 2))),
new XElement("Level1",
new XElement("Item",
new XAttribute("Id", 3)),
new XElement("Item",
new XAttribute("Id", 4))));
Assert.AreEqual(4,
(from element in XML.Elements("Level1").Elements("Item")
select element).Count());
Related
I am building a C# application. I want to insert the following XML data to XML.
<?xml version="1.0" encoding="utf-8"?>
<Employees>
<Employee ID="1">
<Name>Numeri</Name>
</Employee>
<Employee ID="2">
<Name>Ismail</Name>
</Employee>
<Employee ID="3">
<Name>jemu</Name>
</Employee>
</Employees>
Previously I have tried an XML that has not attribute value, But now I
want to insert with attribute value.
string _file = (Application.StartupPath+"/employees.xml");
XDocument doc;
if (!File.Exists(_file))
{
doc = new XDocument();
doc.Add(new XElement("Employees"));
}
else
{
doc = XDocument.Load(_file);
}
doc.Root.Add(
new XElement("Employee",
new XElement("ID", textBox1.Text),
new XElement("Name", textBox2.Text)
)
);
doc.Save(_file);
You should use XAttribute instead of XElement in order to insert ID as attribute:
doc.Root.Add(
new XElement("Employee",
new XAttribute("ID", textBox1.Text),
new XElement("Name", textBox2.Text)
)
);
Hi I am new to XML building, I basically didn't use it before, I always preferred json.
I have a solution where I just make it with string and convert to XML object, but how can I do it with XElement class?
This is the document:
<?xml version="1.0" encoding="utf-8"?>
<requestblock version="3.67">
<alias>ALIAS</alias>
<request type="AUTH">
<operation>
<sitereference>test12345</sitereference>
<accounttypedescription>TEST</accounttypedescription>
<parenttransactionreference>12-3-4567</parenttransactionreference>
</operation>
<merchant>
<orderreference>Example recurring auth</orderreference>
</merchant>
<customer> </customer>
<billing>
<amount currencycode="GBP">1234</amount>
<subscription type="TEST">
<number>1</number>
</subscription>
</billing>
<settlement/>
</request>
</requestblock>
I already have a part of the code like this:
XElement address =
new XElement("alias", "TEST",
new XElement("request", new XAttribute("type", "AUTH"),
new XElement("City", "Mercer Island"),
new XElement("State", "WA"),
new XElement("Postal", "68042")
));
But I have a problem with alias, because alias is closed after all elements, not in the same notation:
<alias>TEST
<request type="AUTH">
<City>Mercer Island</City>
<State>WA</State>
<Postal>68042</Postal>
</request>
</alias>
As you can see notation is the problem.
You're setting alias as your root element, which should be requestblock. If you start with requestblock like this:
XElement address =
new XElement("requestblock", new XAttribute("version",3.67),
new XElement("alias", "TEST"),
new XElement("request", new XAttribute("type", "AUTH"),
new XElement("City", "Mercer Island"),
new XElement("State", "WA"),
new XElement("Postal", "68042")
It'l give you
<requestblock version="3.67">
<alias>TEST</alias>
<request type="AUTH">
<City>Mercer Island</City>
<State>WA</State>
<Postal>68042</Postal>
</request>
</requestblock>
I want create xml file of this structure:
<Devices>
<Device Number="58" Name="Default Device" >
<Functions>
<Function Number="1" Name="Default func" />
<Function Number="2" Name="Default func2" />
<Function Number="..." Name="...." />
</Functions>
</Device>
</Devices>
Here's my code:
document.Element("Devices").Add(
new XElement("Device",
new XAttribute("Number", ID),
new XAttribute("Name", Name),
new XElement("Functions")));
Each object "device" have List<> of "functions", how can i add "functions" to xml???
Each object "device" have List<> of "functions", how can i add "functions" to xml???
Really easily - LINQ to XML makes this a doddle:
document.Element("Devices").Add(
new XElement("Device",
new XAttribute("Number", ID),
new XAttribute("Name", Name),
new XElement("Functions",
functions.Select(f =>
new XElement("Function",
new XAttribute("Number", f.ID),
new XAttribute("Name", f.Name))))));
In other words, you just project your List<Function> to an IEnumerable<XElement> using Select, and the XElement constructor does the rest.
document.Element("Devices").Add(
new XElement("Device",
new XAttribute("Number", ID),
new XAttribute("Name", Name),
new XElement("Functions", from f in functions select new XElement("Function", new XAttribute("Number", f.Number), new XAttribute("Name", f.Name)))));
functions would be your list of functions.
XML:
<Questions>
<Question>
<Id>1</Id>
<Text>aaa</Text>
<Reserver />
</Question>
<Question>
<Id>2</Id>
<Text>bbb</Text>
<Reserver />
</Question>
</Questions>
How can insert new Question using LINQ like this:
<Question>
<Id>3</Id>
<Text>ccc</Text>
<Reserver />
</Question>
XDocument doc = XDocument.Parse("<Questions>...</Questions>");
doc.Root.Add(
new XElement("Question",
new XElement("Id", 3),
new XElement("Text", "ccc"),
new XElement("Reserver"))
);
You can create a new element like this:
var newElem = new XElement("Question",
new XElement("Id", 3),
...
);
xdoc.Root.Add(newElem);
I have a DataTable which I select from database (Well, these data cross several tables, after the query and putting into a DataTable, it shows at below)
ColumnA ColumnB
a 11
b 33
b 44
a 22
b 55
but I want to transform it into an XML like this
<root>
<header name ='a'>
<item name='11' />
<item name='22' />
</header>
<header name ='b'>
<item name='33' />
<item name='44' />
<item name='55' />
</header>
</root>
Is there an easy way to implement it by C#?
Why bother with C# ?? You can do it in T-SQL directly (SQL Server 2005 and up):
SELECT
ColumnA AS '#name',
(SELECT ColumnB AS '#name'
FROM YourTable t
WHERE t.ColumnA = YourTable.ColumnA
FOR XML PATH('item'), TYPE)
FROM
YourTable
GROUP BY
ColumnA
FOR XML PATH('header'), ROOT('root')
Gives you:
<root>
<header name="a">
<item name="11" />
<item name="22" />
</header>
<header name="b">
<item name="33" />
<item name="44" />
<item name="55" />
</header>
</root>
You can execute this SQL query using standard ADO.NET SqlCommand and get back the XML nicely formatted already.
Marc
OK, second approach after learning that the data is available in a DataTable to begin with.
The code is a bit more involved, since based on a DataTable, you can't really do much in terms of grouping etc. I am building up the XmlDocument (since you're on .NET 2.0) while scanning through the rows of data. I need to keep track of the <header> elements in a dictionary, in order to add a second, third entry with the same "ColumnA" value to that already existing XmlElement in the document - it's a bit involved, but if you study it carefully, I hope you see it's really no trickery or anything - just a bit of bookkeeping along the way of building the XmlDocument:
// create the XmlDocument and add <root> node
XmlDocument doc = new XmlDocument();
doc.AppendChild(doc.CreateElement("root"));
// dictionary to keep track of <header> nodes
Dictionary<string, XmlNode> nodesPerColumnA = new Dictionary<string, XmlNode>();
// Loop through data rows
foreach (DataRow row in tbl.Rows)
{
// extract values for ColumnA and ColumnB as strings
string columnAValue = row["ColumnA"].ToString();
string columnBValue = row["ColumnB"].ToString();
// create a new <item> XmlNode and fill its attribute #Name
XmlElement newNode = doc.CreateElement("item");
XmlAttribute newNodeAttribute = doc.CreateAttribute("name");
newNodeAttribute.InnerText = columnBValue;
newNode.Attributes.Append(newNodeAttribute);
// check if we already have a <header> node for that "ColumnA" value
if(nodesPerColumnA.ContainsKey(columnAValue))
{
// if so - just add <item> below that <header>
XmlNode parent = nodesPerColumnA[columnAValue];
parent.AppendChild(newNode);
}
else
{
// if not - create appropriate <header> node and its #name attribute
XmlElement header = doc.CreateElement("header");
XmlAttribute headerAttr = doc.CreateAttribute("name");
headerAttr.InnerText = columnAValue;
header.Attributes.Append(headerAttr);
header.AppendChild(newNode);
doc.DocumentElement.AppendChild(header);
// store that <header> xmlnode into the dictionary for future use
nodesPerColumnA.Add(columnAValue, header);
}
}
// check the contents of the XmlDocument at the end
string xmlContents = doc.InnerXml;
With LINQ:-
var qry = from row in Table
group row by row.ColumnA into header
select header;
var elem = new XElement("root");
foreach (var header in qry)
{
var elemHead = new XElement("header", new XAttribute("name", header.Key));
elem.Add(elemHead);
foreach (var item in header)
elemHead.Add(new XElement("item", new XAttribute("name", item.ColumnB)));
}
// the variable elem contains the result.
This will do it using .NET 3.5 and the XDocument
XDocument yourDocument = new XDocument(new XElement("root",
new XElement("header",
new XAttribute("name", "a"),
new XElement("item",
new XAttribute("name", "11")),
new XElement("item",
new XAttribute("name", "22"))),
new XElement("header",
new XAttribute("name", "b"),
new XElement("item",
new XAttribute("name", "33")),
new XElement("item",
new XAttribute("name", "44")),
new XElement("item",
new XAttribute("name", "55")))));