Updating XML Tags Attributes Values in .NET - vb.net

I have an xml string like that
<root>
Am trying <br id="9"/>to reorder the <br id="5"/>break
lines <br id="10"/> attributes value
</root>
Any Way to change attribute value of XML BR tag ID attribute to be in sequence
like this
<root>
Am trying <br id="1"/>to reorder the <br id="2"/>break
lines <br id="3"/> attributes value
</root>

Here is one example using LINQ TO XML
Dim doc as XElement = <root>
Am trying <br id="9"/>to reorder the <br id="5"/>break
lines <br id="10"/> attributes value
</root>
Dim index as Integer = 0
For Each br In doc.<br>
index += 1
br.#id = index
Next
This results in the following output
<root>
Am trying <br id="1" />to reorder the <br id="2" />break
lines <br id="3" /> attributes value
</root>
Also, here's an example using a LAMBDA expression.
doc.<br>.ToList().ForEach(Sub(br)
index += 1
br.#id = index
End Sub)

Related

How to insert XML to SQL

I try to add a XML file to SQL 2008.
My XML:
<ItemList>
<Section Index="0" Name="cat0">
<Item Index="0" Slot="0" />
<Item Index="1" Slot="0" />
</Section>
<Section Index="1" Name="cat1">
<Item Index="33" Slot="0" />
<Item Index="54" Slot="0" />
</Section>
<Section Index="2" Name="cat2">
<Item Index="55" Slot="0" />
<Item Index="78" Slot="0" />
</Section>
</ItemList>
SQL Column :
Name = Section Name,
Cat = Section Index,
Index = Item Index,
Slot = Item Slot.
My Example :
DECLARE #input XML = 'MY XML file'
SELECT
Name = XCol.value('#Index','varchar(25)'),
Cat = XCol.value('#Name','varchar(25)'),
[Index] = 'Unknown', /* Index from <Item>*/
Slot = 'Unknown' /* Slot from <Item> */
FROM #input.nodes('/ItemList/Section') AS test(XCol)
I don't know how to add values from "Item".
Thank you very much!
You can do it like this:
select
Name = XCol.value('../#Index','varchar(25)'),
Cat = XCol.value('../#Name','varchar(25)'),
[Index] = XCol.value('#Index','varchar(25)'),
Slot = XCol.value('#Slot','varchar(25)')
from
#input.nodes('/ItemList/Section/Item') AS test(XCol)
Key idea: take data one level deeper, not /ItemList/Section, but /ItemList/Section/Item. So in this case you are able to access attributes of Item and also you can access attributes of parent element (Section in your case) by specifying ../#Attribute_Name
Different than the previous answer - CROSS APPLY with the children Item nodes:
SELECT
Name = XCol.value('#Index','varchar(25)'),
Cat = XCol.value('#Name','varchar(25)'),
[Index] = XCol2.value('#Index','varchar(25)'),
Slot = XCol2.value('#Slot','varchar(25)')
FROM #input.nodes('/ItemList/Section') AS test(XCol)
CROSS APPLY XCol.nodes('Item') AS test2(XCol2)

update xml attribute in xml returns error SQL

Im trying to update an attribute of an xml in SQL.
My XML is stored on a variable #tmpRespXML:
<Responses>
<x id="3" name="Good" val="0" seq="0" createsr="0" />
<x id="4" name="Fair" val="0" seq="0" createsr="0" />
<x id="5" name="Needs Repair" val="1" seq="0" createsr="0" />
<x id="6" name="Not Inspected" val="1" seq="0" createsr="0" />
<x id="7" name="N/A" val="1" seq="0" createsr="0" />
</Responses>
So what I did is to put the xml in a temp table.
DECLARE #tmpRespTBL TABLE(Responses XML)
INSERT #tmpRespTBL VALUES(#tmpRespXML)
and then update the table. I'm trying to set the attribute #createsr to 1 where my attribute #id is equal to #items
UPDATE #tmpRespTBL
SET Responses.modify('replace value of(/Responses/x[#id=("'+#items+'")]/#createsr)[1] with "1"')
This returns the ff error:
Msg 8172, Level 16, State 1, Line 30 The argument 1 of the xml data
type method "modify" must be a string literal.
What am I missing here?
Try with
SET Responses.modify('replace value of(/Responses/x[#id=("''+#items+''")]/#createsr)[1] with "1"')
That should fix your issue. What I did here is escape the '

DbUnit Assertion floating-point numbers

I'm testing my DAO layer using DbUnit. I'm prefilling database from XML dataset, doing some actions and then asserting against known result.
Assertion.assertEquals(expectedDataSet, actualDataSet);
Dataset contains column with floating point number. Then these columns are compared, I get:
junit.framework.ComparisonFailure: value (table=OrderLine_T, row=2, col=price) expected:<2.99[]> but was:<2.99[0000009536743]>.
The values are equal, but because floating-point numbers cannot be exactly represented in binary form, the assertion fails.
In JUnit we have assertEquals(double expected, double actual, double delta). How do we set some delta in DbUnit for floating-point number comparison ?
Initial dataset:
<dataset>
<Customer_T id="1" name="Anthony"/>
<Customer_T id="2" name="John"/>
<Order_T id="1" date="2012-06-07 14:30" customer_id="1" />
<Order_T id="2" date="2012-06-07 15:31" customer_id="2" />
<OrderLine_T id="1" order_id="1" product_id="1" price="2.99" quantity="5" />
<OrderLine_T id="2" order_id="2" product_id="2" price="3.49" quantity="10" />
</dataset>
Expected result:
<dataset>
<Customer_T id="1" name="Anthony"/>
<Customer_T id="2" name="John"/>
<Order_T id="1" date="2012-06-07 14:30" customer_id="1" />
<Order_T id="2" date="2012-06-07 15:31" customer_id="2" />
<OrderLine_T id="1" order_id="1" product_id="1" price="2.99" quantity="5" />
<OrderLine_T id="2" order_id="2" product_id="2" price="3.49" quantity="10" />
<!-- Below added -->
<Order_T id="3" date="1987-06-07 9:15:10" customer_id="2" />
<OrderLine_T id="3" order_id="3" product_id="1" price="2.99" quantity="2" />
<OrderLine_T id="4" order_id="3" product_id="5" price="3.55" quantity="8" />
</dataset>
Code:
/* Should save order correctly (including order lines) */
#Test
public void save() throws Exception {
/* Create new order */
Set<OrderLine> lines = new HashSet<OrderLine>();
lines.add(new OrderLine(1, (float)2.99, 2));
lines.add(new OrderLine(5, (float)3.55, 8));
Calendar cal = Calendar.getInstance();
cal.set(1987, 6, 7, 9, 15, 10);
Date date = cal.getTime();
Customer customer = customerDAO.findById(2); // John
Order order = new Order(date, lines, customer);
orderDAO.save(order);
entityManager.flush();
/* Assert order is saved */
IDataSet expectedDataSet = new FlatXmlDataSetBuilder().build(Thread.currentThread()
.getContextClassLoader()
.getResourceAsStream("data-set-afterAddOrder.xml"));
IDataSet actualDataSet = getDatabaseConnection().createDataSet();
Assertion.assertEquals(expectedDataSet, actualDataSet);
}
Edit:
Probably need to mention what I'm using in-memory HSQLDB. Just tried MySQL and it passes successfully.
Tried setting ToleratedDelta without success:
IDatabaseConnection connection = new DatabaseConnection(((SessionImpl) (entityManager.getDelegate())).connection());
HsqldbDataTypeFactory dataTypeFactory = new HsqldbDataTypeFactory();
dataTypeFactory.addToleratedDelta(new ToleratedDelta("OrderLine_T", "price", 0.01));
connection.getConfig().setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, dataTypeFactory);
Edit2:
I was using hibernate.hbm2ddl.auto = create, to export schema to database. After got idea from fredt, I changed the type of field price on my entity to BigDecimal and added additional column precision and scale params:
#Column(precision=10, scale=4)
private BigDecimal price;
This gets translated to PRICE NUMERIC(10,4). Problem solved, thanks to fredt.
If the column is defined as DECIMAL or NUMERIC with the required precision and scale, the value will have the exace number of digits after the decimal point and the issue can be avoided.

SQL Server XML add attribute if non-existent

I am trying to add an attribute if it does not exist. It should be simple, but I am new to XML XPath/XQuery/etc., so excuse my ignorance.
I want to be able to pass XML data and modify it...
ALTER FUNCTION [dbo].[ConvertXmlData](#xmlData XML)
RETURNS XML
AS
BEGIN
RETURN #xmlData.<something here>
END
If I pass data like:
<something>
this is sample data <xxx id="1"/> and <xxx id="2" runat="server" />. More <yyy id="3" />
</something>
I would like
<something>
this is sample data <xxx id="1" runat="server" /> and <xxx id="2" runat="server" />. More <yyy id="3" />
</something>
And not :
<something>
this is sample data <xxx id="1" runat="server" /> and <xxx id="2" runat="server" runat="server"/>. More <yyy id="3" />
</something>
You can do
SET #xmlData.modify('insert attribute runat { "server" } into descendant::xxx[not(#runat)][1]');
This will however only change the first xxx descendant not having a runat attribute, at least with SQL Server 2005 you can only modify one node at a time.
Maybe combining the above with a WHILE helps e.g.
WHILE #xmlData.exist('descendant::xxx[not(#runat)]') = 1
BEGIN
SET #xmlData.modify('insert attribute runat { "server" } into descendant::xxx[not(#runat)][1]');
END
I don't have access to SQL Server 2008 R2 but I think the modify is still limited to one node at a time so you could try
ALTER FUNCTION [dbo].[ConvertXmlData](#xmlData XML)
RETURNS XML
AS
BEGIN
WHILE #xmlData.exist('descendant::xxx[not(#runat)]') = 1
BEGIN
SET #xmlData.modify('insert attribute runat { "server" } into descendant::xxx[not(#runat)][1]');
END
RETURN #xmlData
END

2 series on my chart

I would like to show 2 series on the same chart, however I'm not sure how to update the following code:
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="UcSalesSeries.ascx.cs" Inherits="Silverlight.ConfigEnhanced.Web.UcSalesSeries" %>
<asp:Chart ID="Chart1" runat="server" DataSourceID="LinqDataSource1"
Height="500px" Width="750px" >
<Series>
<asp:Series ChartType="Line" Name="Series1" XValueMember="EndOfMonth"
YValueMembers="Quantity" >
</asp:Series>
</Series>
<Series>
<asp:Series ChartType="Line" Name="Series2" XValueMember="EndOfMonth"
YValueMembers="Quantity" >
</asp:Series>
</Series>
<ChartAreas>
<asp:ChartArea Name="ChartArea1">
</asp:ChartArea>
</ChartAreas> <Legends>
<asp:Legend TableStyle="Auto" Docking="Top" >
</asp:Legend>
</Legends>
</asp:Chart>
<asp:LinqDataSource ID="LinqDataSource1" runat="server"
ContextTypeName="Data.DataClasses1DataContext" EntityTypeName="" Select="new (EndOfMonth, Quantity)"
TableName="T_SalesDatas" OrderBy="EndOfMonth" Where="Model == #Model">
<WhereParameters>
<asp:Parameter DefaultValue="XXS" Name="Model" Type="String" />
</WhereParameters>
</asp:LinqDataSource>
the second serie I would like to see is the same as above, but I would be changing the parameter
<asp:Parameter DefaultValue="NEWVALUE" Name="Model" Type="String" />
The Chart does not support multiple DataSources so you will need to manually add the points from code behind to the chart when rendering the page. You create two tables from your data with the different parameters and iterate each table and adding them to the chart manually.
Read more in the section 'Manual' series population on this MSDN blog:
http://blogs.msdn.com/b/alexgor/archive/2009/02/21/data-binding-ms-chart-control.aspx