I have the following XML
<xml>
<ObsCont xCampo="field1">
<xTexto>example1</xTexto>
</ObsCont>
<ObsCont xCampo="field2">
<xTexto>example2</xTexto>
</ObsCont>
<ObsCont xCampo="field3">
<xTexto>example3</xTexto>
</ObsCont>
<field>information</field>
</xml>
Is there a way to get the content of "xTexto" inside the ObsCont that has "field2" value for the attribute xCampo using DataSet ?
It would be desireable to have a single liner like the following:
DataSet ds = new DataSet();
ds.ReadXml(StrArquivoProc);
ds.Tables["xml"].Rows[0]["field"].ToString();
//field == "information"
If I use the same method I'm not specifying that I want the one with the desired attribute.
If you have an absolutely known data path then you can use XPath:
Dim myFile = "c:\test.xml"
Dim X As New System.Xml.XmlDocument()
X.Load(myFile)
Dim N = X.SelectSingleNode("//xml/ObsCont[#xCampo=""field2""]/xTexto")
Trace.WriteLine(N.InnerText)
You could certainly use something like Linq to XML to load the entire document into a collection that you could further query or iterate over to use to whatever ends you desire, including binding to data controls. Or you could specifically query the document directly for the desired attribute/element value combination, like below.
XDocument document = XDocument.Parse(xml);
// or document = XDocument.Load(xmlFile)
// System.Xml.Linq namespace
var query = (from obscont in document.Descendants("ObsCont")
where obscont.Attribute("xCampo").Value == "field2"
select obscont.Element("xTexto").Value).First();
Console.WriteLine(query);
Here's the XPathDocument version of Chris Haas' solution, for what it's worth.
Dim myFile = "c:\test.xml"
Dim fs As New FileStream(myFile, FileMode.Open)
Dim doc As New XPathDocument(fs)
fs.Dispose()
Dim nav = doc.CreateNavigator()
Dim node = nav.SelectSingleNode("//xml/ObsCont[#xCampo=""field2""]/xTexto")
Trace.WriteLine(node.Value)
Or if you have the XML in a string, use a StringReader instead.
Dim doc As New XPathDocument(New StringReader(myXml))
'And so forth...'
Related
I have and datable and a column of string data type in that column i put content of type ddl some like
create table
create view
create stored procedure
dt.columns("content") = "create procedure ...etc"
that work ok,
the problem is when i need recovery the content like xml. Now i do that with
Dim xmlcontent = dt.DataSet.GetXml().ToString()
that return a xml like
<NewDataSet>
<Application_table>
<ID>PV</ID>
<NAme>dbo.uvw_Sample</Nombre>
<Content>/*
Run this script on SQL Server 2008 or later. There may be flaws if running on earlier versions of SQL Server.
*/
Create View...
...
</Content>
</Application_table>
</NewDataSet>
the exception is
XML parsing: line 5349, character 59, illegal xml character
i think the content in column content should for example change "<" for "<" or better specifiy the content like cdata
So I want to specify that the serialization of the column be as CDATA. Anyone know if there is way to do it?
You can try converting the nodes in question to a cdata node. This code might be obsolete as its very old, but it still works. I made an xml document from the dataset. Changed all the text nodes to CDATA nodes. Here is the code:
workingds = DataSetWithData
'Convert dataset to xmldatadocument
Dim myxmldoc As Xml.XmlDataDocument = New Xml.XmlDataDocument(workingds)
txtnodes = myxmldoc.GetElementsByTagName(strTextField)
For i = 0 To txtnodes.Count - 1
Me.makecdata(txtnodes(i))
Next i
'this subroutine takes the text node and wraps a cdata tag around it
'and returns it to the document
Public Sub makecdata(ByVal mynode As Xml.XmlNode)
Dim mcnode As Xml.XmlCDataSection, strtemp As String
strtemp = mynode.InnerText
mcnode = (mynode.OwnerDocument.CreateCDataSection(strtemp))
mynode.InnerXml = ""
mynode.AppendChild(mcnode)
mcnode = Nothing
End Sub
Use serialization:
private string DataSetToXml(DataSet ds)
{
using (var ms= new MemoryStream())
{
using (TextWriter sw= new StreamWriter(ms))
{
var xmlSerializer = new XmlSerializer(typeof(DataSet));
xmlSerializer.Serialize(sw, ds);
return Encoding.UTF8.GetString(memoryStream.ToArray());
}
}
}
or you can use .getXml() returned xml se how you can serialize into string Using StringWriter for XML Serialization
I have this xml file with several levels for node's childs:
-product
--name
--price
--made
-----product
--------name
--distributor
-----name
------address
/product
I need to read it in sequence, but it's not possible with XmlReader, so I have to use XmlDocument to read each node and copy into DataSet (or similar).
How can I read node by node and copy to dataset in C# ??? Any help please?
Convert xml string to DataSet using StringReader
string xmlData = "<product><name></name><price></price><made></made></product>";
StringReader reader = new StringReader(xmlData);
DataSet ds = new DataSet();
ds.ReadXml(reader);
Write XML Data into a DataSet directly from xml file:
string myfile = #"C:\myXml.xml";
DataSet ds = new DataSet();
ds.ReadXml(myfile);
I think you can use Xpath over XMl Document to read node by node.
It is possible using XDocument and LINQ-to-XML:
XDocument doc = XDocument.Load("test.xml");
// Create two DataTable instances.
DataTable table1 = new DataTable("patients");
table1.Columns.Add("name");
foreach(var name in doc.Root.DescendantNodes().OfType<XElement>()
.Select(x => x.Name).Distinct())
{
table1.Rows.Add(name);
Console.WriteLine(name);
}
There is a nice example on the Microsoft Website (Even vor .Net 4)
Dim xmlDoc As XmlDataDocument = New XmlDataDocument(dataSet)
Dim xslTran As XslTransform = New XslTransform
xslTran.Load("transform.xsl")
Dim writer As XmlTextWriter = New XmlTextWriter("xslt_output.html", System.Text.Encoding.UTF8)
xslTran.Transform(xmlDoc, Nothing, writer)
http://technet.microsoft.com/en-us/query/8fd7xytc
No unfortunately XmlDataDocument is deprecated, but nobody seems to have a good answer on how to replace it in this situation?
You can use the following code.
Use DataSet.GetXml() to get the xml as string and then create an XDocument by parsing the string:
string xml = dataSet.GetXml();
XDocument document = XDocument.Parse(xml);
The setup of the transformation and its output is the same, except using XslCompiledTransform:
XslCompiledTransform transform = new XslCompiledTransform();
transform.Load("transform.xsl");
XmlTextWriter writer = new XmlTextWriter("Output.xml", System.Text.Encoding.UTF8);
And then you can use the XslCompiledTransform.Transform() overload that takes a reader as the first argument, which you can get from calling XDocument.CreateReader():
transform.Transform(Document.CreateReader(), writer);
I am having a problem parsing xml that I receive from Web Service.
The xml looks very simple:
<Result xsi:schemaLocation="urn:yahoo:developer http://developer.yahooapis.com/TimeService/V1/GetTimeResponse.xsd" type="web"><Timestamp>1320677359</Timestamp></Result>
But when I try to parse it with following code I am getting no return results.
XDocument doc = XDocument.Load("http://developer.yahooapis.com/TimeService/V1/getTime?appid=StackSolution");
var datestamp = from ds in doc.Descendants("Result")
select new { currentstamp = ds.Element("Timestamp").Value };
Is there a solution or way to parse it?
Thanks you in advance
You have a couple issues: First, the Result node isn't a descendant. It's the root. Second, you ran into the most common issue when using LINQ to XML - you forgot the namespace. The following should give you what you need:
XElement doc = XElement.Load("http://developer.yahooapis.com/TimeService/V1/getTime?appid=StackSolution");
XNamespace ns = "urn:yahoo:developer";
var datestamp = from ds in doc.DescendantsAndSelf(ns + "Result")
select new { currentstamp = ds.Element(ns + "Timestamp").Value };
Note, this produces an IEnumerable. If you only want the datestamp, consider using FirstOrDefault instead. You may be able to make this simpler by just doing the following:
XElement doc = XElement.Load("http://developer.yahooapis.com/TimeService/V1/getTime?appid=StackSolution");
XNamespace ns = "urn:yahoo:developer";
var datestamp = doc.Element(ns + "Timestamp").Value;
This method avoids the namespace issue using LocalName (unqualified identifier).
var datestamp = doc.Root.Descendants().Where(c => c.Name.LocalName.Equals("Timestamp")).FirstOrDefault().FirstNode.ToString()
How would i go about to remove all comment tags from a XmlDocument instance?
Is there a better way than retrieving a XmlNodeList and iterate over those?
XmlNodeList list = xmlDoc.SelectNodes("//comment()");
foreach(XmlNode node in list)
{
node.ParentNode.RemoveChild(node);
}
When you load the xml, you can use XmlReaderSettings
XmlReaderSettings settings = new XmlReaderSettings();
settings.IgnoreComments = true;
XmlReader reader = XmlReader.Create("...", settings);
xmlDoc.Load(reader);
On an existing instance, your solution looks good.
Nope thats about it, although I'd be inclind to place the nodes in a List first.
I'm not sure about the .NET implementation of XmlNodeList but I know that previous MSXML implementations loaded the list in lazy manner and code such as the above in the past would end up failing in some way as result of the DOM tree being modified as the List is enumerated.
foreach (var node in xml.SelectNodes("//comment()").ToList())
node.ParentNode.RemoveChild(node);
Today looking for the way how to extract <!-- --> from Visual Basic for Applications (not C#), I have found also nodeTypeString property, but it takes more space. Here is an example in VBA:
Dim xmldoc As New MSXML2.DOMDocument30
Dim oNodeList As IXMLDOMSelection
Dim node As IXMLDOMNode
Dim i As Long
Dim FileName As String, FileName1 As String
FileName = "..." ' Source
FileName2 = "..." ' Target
xmldoc.async = False ' ?
xmldoc.Load FileName
If (xmldoc.parseError.errorCode <> 0) Then Exit Sub ' or Function
Set oNodeList = xmldoc.selectNodes("//*") '' all nodes
For i = 0 To oNodeList.length - 1
With oNodeList(i)
For Each node In .childNodes
If node.nodeTypeString = "comment" Then .removeChild node
Next
End With
Next
xmldoc.Save FileName2
Set oNodeList = Nothing ' ?
Set xmldoc = Nothing
It omitts document top parent comment nodes, but they can be retrieved somehow directly if needed, for example using With xmldoc.documentElement.childNodes.