how can i retrieve node out of xml document by inner text.
for example
<w:t>WARNING</w:t>
node consists multiple times with different values in xml document.
I want to retrieve only those w:t nodes with inner text contains "WARNING" .
how can it be done?
To query elements with prefix you have to register proper prefix-to-namespace-URI mapping using XmlNamespaceManager, then use that registered prefix in your XPath, for example :
var xml = #"<root xmlns:w=""test"">
<w:t>WARNING</w:t>
</root>";
var xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xml);
var nsManager = new XmlNamespaceManager(xmlDoc.NameTable);
//register proper prefix-to-namespace-URI mapping
nsManager.AddNamespace("w", "test");
//following XPath used to select <w:t> nodes with inner text contains "WARNING"
var result = xmlDoc.DocumentElement.SelectSingleNode("//w:t[contains(., 'WARNING')]", nsManager);
//print result
Console.WriteLine(result.OuterXml);
Try this :
var wtNodes = elements.Where(e => e.Name.LocalName.Equals("w:t"));
var warningNodes = wtNodes.Where(node => node.Value.Contains("WARNING"));
Try this:
xmlNodeList xNlist= xDoc.selectNodes("//pre:t[.="WARNING"]",objXmlnsMgr);
Here:
xDoc is XmlDocument;
objXmlnsMgr is XmlNamespaceManager ('w' in your case) & pre is its prefix.
Related
I am new to C#, kindly help me. How to remove the single xml element node 'PaymentRecord' and content inside that should not get deleted.
<Payments>
<PaymentRecord>
<PayId>2031</PayId>
<Reference>Policy03</Reference>
<StatusCode>ACV</StatusCode>
<MethodDetail>
<PaymentMethodDetail>
<CardPaymentDetails>
<CardHolderName>abcded</CardHolderName>
<CardTransactionDetails>
<StoredCard>N</StoredCard>
</CardTransactionDetails>
</CardPaymentDetails>
</PaymentMethodDetail>
</MethodDetail>
<CurrencyCode>USD</CurrencyCode>
</PaymentRecord>
</Payments>
I need to remove "PaymentRecord" element from the XML. I need like below
<Payments>
<PayId>2031</PayId>
<Reference>Policy03</Reference>
<StatusCode>ACV</StatusCode>
<MethodDetail>
<PaymentMethodDetail>
<CardPaymentDetails>
<CardHolderName>abcded</CardHolderName>
<CardTransactionDetails>
<StoredCard>N</StoredCard>
</CardTransactionDetails>
</CardPaymentDetails>
</PaymentMethodDetail>
</MethodDetail>
<CurrencyCode>USD</CurrencyCode>
</Payments>
I have tried my below code, but its deleting the complete node which I don't want to do :- here 'queuePayload' is the xml element
XmlNodeList payloadRecordList = queuePayload.SelectNodes("//Payments/PaymentRecord");
foreach (XmlElement singleNode in payloadRecordList)
{
XmlHelper.removeElem((XmlElement)singleNode.ParentNode, "//PaymentRecord");
XmlDocument xmlDoc = singleNode.OuterXml;
// my remaining logic goes based on "xmldoc" value - I will inserting this data to table
}
You can use System.Xml.Linq with its XDocument to achiev this. Load the input and create a new document out of it like:
XDocument inputDoc = XDocument.Load(inputFile, LoadOptions.None);
XDocument outputDoc = new XDocument();
var elements = inputDoc.Element("Payments").Elements().Select(pr => pr.Elements());
XElement newElement = new XElement("Payments");
foreach (var element in elements)
{
newElement.Add(element);
}
outputDoc.Add(newElement);
Console.WriteLine(outputDoc.ToString());
I think #Fructzwerg is slightly overcomplicating it.
You can remove the PaymentRecord node and add all its children to the root in one go.
var xDoc = XDocument.Load(filePath);
var paymentRecord = xDoc.Root.Element("PaymentRecord");
var nodes = xDoc.Root.Element("PaymentRecord").Elements();
paymentRecord.Remove();
xDoc.Root.Add(nodes);
Console.WriteLine(xDoc.ToString());
dotnetfiddle
I have xml file:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><SENT_110 xmlns:ns2="http://www.mf.gov.pl/SENT/2017/01/18/STypes.xsd" xmlns="http://www.mf.gov.pl/SENT/2017/01/18/SENT_110.xsd"><SentNumber>SENT20180416000032</SentNumber><KeyNumber><ns2:SenderKey>KS-28YM</ns2:SenderKey><ns2:RecipientKey>KR-52DH</ns2:RecipientKey><ns2:CarrierKey>KD-48WW</ns2:CarrierKey></KeyNumber>
I want to read in separate SenderKey, RecipientKey & CarrierKey.
When i use this code:
XmlTextReader reader = new XmlTextReader(file);
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(reader);
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
nsmgr.AddNamespace("ns", xmlDoc.DocumentElement.NamespaceURI);
XmlNodeList nodeList = xmlDoc.SelectNodes("/ns:SENT_110/ns:KeyNumber", nsmgr);
foreach (XmlNode node in nodeList)
{
key = node.InnerText;
MessageBox.Show(key);
}
i've got something like this: KS-28YMKR-52DHKD-48WW, without any separate between key.
How i could read only one key?
Use the following XPath:
"/ns:SENT_110/ns:KeyNumber/*"
It will return all nested nodes to you.
If the structure of the XML is fixed it is rather easy by using XDocument:
var xmlText = "<SENT_110 xmlns:ns2=\"http://www.mf.gov.pl/SENT/2017/01/18/STypes.xsd\" xmlns=\"http://www.mf.gov.pl/SENT/2017/01/18/SENT_110.xsd\"><SentNumber>SENT20180416000032</SentNumber><KeyNumber><ns2:SenderKey>KS-28YM</ns2:SenderKey><ns2:RecipientKey>KR-52DH</ns2:RecipientKey><ns2:CarrierKey>KD-48WW</ns2:CarrierKey></KeyNumber></SENT_110>";
var xml = XDocument.Parse(xmlText);
var nodes = xml.Descendants();
var senderKey = nodes.First(d => d.Name.ToString().EndsWith("SenderKey")).Value;
var recipientKey = nodes.First(d => d.Name.ToString().EndsWith("RecipientKey")).Value;
var carrierKey = nodes.First(d => d.Name.ToString().EndsWith("CarrierKey")).Value;
See HERE for a working snippet. If this is just a part of a bigger XML or the structure can be different maybe some more complex searching is needed.
I have the following XML File. I want to copy a new "Test" and change the ID of the Test. How is it possible?
I already can copy the nodes, unfortunately not on the correct position (see images) and I also canĀ“t change the ID.
Anyone have a solution for me?
Before:
After:
XmlDocument xmldoc = new XmlDocument();
xmldoc.Load(Before.xml");
XmlNode Set = xmldoc.DocumentElement;
string strXmlQuery = "/Toolings/Testing/Test1";
XmlNode NodeToCopy = Set.SelectSingleNode(strXmlQuery);
XmlNode NewNode = NodeToCopy.CloneNode(true);
NodeToCopy.AppendChild(NewNode);
Set.InsertAfter(NewNode, Set.LastChild);
XPathNavigator navigator = xmldoc.CreateNavigator();
navigator.MoveToRoot();
navigator.MoveToFirstChild();
navigator.MoveToFirstChild();
navigator.MoveToFirstChild();
navigator.MoveToFirstChild();
navigator.SetValue("5678");
xmldoc.Save(After.xml");
Here is an example using System.Xml.Linq.XDocument which is a much easier API than XmlDocument:
//You can also use Load(), this is just so I didn't have to make a file
XDocument doc = XDocument.Parse("<Toolings><Testing><Test><ID>1234</ID></Test></Testing></Toolings>");
//Grab the first Test node (change the predicate if you have other search criteria)
var elTest = doc.Descendants().First(d => d.Name == "Test");
//Copy the node, only necessary if you don't know the structure at design time
XElement el = new XElement(elTest);
el.Element("ID").Value = "5678";
//inject new node
elTest.AddAfterSelf(el);
doc.Save("After.xml");
I am trying to delete a whole XmlNode which matches a certain condition
The format of my xml file is as follows:
<?xml version="1.0" encoding="utf-8"?>
<Advertisements>
<Ad>
<ImageUrl>image/Hydrangeas.jpg</ImageUrl>
<NavigateUrl>www.google.com</NavigateUrl>
<AlternateText>nbfndbf</AlternateText>
<ID>0</ID>
<Impressions>1</Impressions>
</Ad>
</Advertisements>
My deleting code:
XElement x =
new XElement("Ad",
new XElement("ImageUrl", lblImageURL.Text),
new XElement("NavigateUrl", lblImageURL.Text),
new XElement("AlternateText", lblAlternateText.Text),
new XElement("ID", lblID.Text),
new XElement("Impressions", lblfrequency.Text));
string filepath = Request.PhysicalApplicationPath.ToString() + "Adrotator.xml";
XmlDocument xD = new XmlDocument();
xD.LoadXml(x.ToString());
XmlNode xN = xD.FirstChild;
xN.ParentNode.RemoveChild(xN);
**xD.Save(filepath);**
I am getting an error Invalid XML document. The document does not have a root element.
You can use linq to xml to achieve this here exmple how to remove node where value ID = 0
var q = (from c in doc.Descendants("Advertisements")
from v in c.Elements("Ad")
where (int) v.Element("ID") == 0
select v).Remove();
here is another example using xpath
doc.XPathSelectElement("Advertisements/Ad[ID = 0]").Remove();
You create a new XDocument (doc) with the following code:
XDocument doc = XDocument.Load(filepath);
Is there something in the Xml file (with a root element)? Also, you don't seem to use doc in the code, so it's at least not required.
Having an XML document, I want to get the first node with a certain name, no matter in which nesting depth it is contained.
I tried several things without success:
var node1 = doc.SelectSingleNode(#"//Shortcut");
var node2 = doc.SelectSingleNode(#"/*/Shortcut");
var node3 = doc.SelectSingleNode(#"//*/Shortcut");
var node4 = doc.SelectSingleNode(#"*/Shortcut");
...
Each call results in a NULL node.
I think it should be some trivial XPath syntax. Can you help me?
(In case this matters: The XML document is an input file for a WiX project, so there could be some namespace issues involved?!?).
Edit
I also tried the following:
var nsm = new XmlNamespaceManager(doc.NameTable);
nsm.AddNamespace(string.Empty, #"http://schemas.microsoft.com/wix/2006/wi");
nsm.AddNamespace(#"ns", #"http://schemas.microsoft.com/wix/2006/wi");
together with:
var node1 = doc.SelectSingleNode(#"//Shortcut", nsm);
var node2 = doc.SelectSingleNode(#"/*/Shortcut", nsm);
var node3 = doc.SelectSingleNode(#"//*/Shortcut", nsm);
var node4 = doc.SelectSingleNode(#"*/Shortcut", nsm);
...
Leading to the same results.
Edit 2 - Solution
I found the solution:
var nsm = new XmlNamespaceManager(doc.NameTable);
nsm.AddNamespace(string.Empty, #"http://schemas.microsoft.com/wix/2006/wi");
nsm.AddNamespace(#"ns", #"http://schemas.microsoft.com/wix/2006/wi");
and then
var node1 = doc.SelectSingleNode(#"//ns:Shortcut", nsm);
This succeeded.
The XPath expression that selects exactly the wanted node (and nothing in addition) is:
(//x:Shortcut)[1]
So, using:
doc.SelectNodes("(//x:Shortcut)[1]", someNamespaceManager)
where
the prefix "x" is bound to the namespace "http://schemas.microsoft.com/wix/2006/wi"
in someNamespaceManager
This has an advantage over the proposed solution (to use SelectSingleNode()), because it can easily be adjusted to select the N-th wanted node in the XML document.
For example:
(//x:Shortcut)[3]
selects the 3rd (in document order) x:Shortcut element, and
(//x:Shortcut)[last()]
selects the last (in document order) x:Shortcut element in the XML document.
Why do not use XDocument?
XDocument doc = XDocument.Load("test.xml");
doc.Descendants("Shortcut").First();
IMO XDocument is faster and more readable than XPath.
I finally found the solution by myself:
var nsm = new XmlNamespaceManager(doc.NameTable);
nsm.AddNamespace(string.Empty, #"http://schemas.microsoft.com/wix/2006/wi");
nsm.AddNamespace(#"ns", #"http://schemas.microsoft.com/wix/2006/wi");
and then
var node1 = doc.SelectSingleNode(#"//ns:Shortcut", nsm);
This succeeded.