i have a problem with my xml.
i need to remove all the the tags that are not in my list
but its not working in the dd tag
here is the xml input
http://pastebin.com/J8KkkMDJ
here is my list. this list are the tags that are only allowed in the xml
lstApprove.Add("Styles");
lstApprove.Add("alto");
lstApprove.Add("Description");
lstApprove.Add("MeasurementUnit");
lstApprove.Add("sourceImageInformation");
lstApprove.Add("fileName");
lstApprove.Add("OCRProcessing");
lstApprove.Add("preProcessingStep");
lstApprove.Add("processingSoftware");
lstApprove.Add("softwareCreator");
lstApprove.Add("softwareName");
lstApprove.Add("softwareVersion");
lstApprove.Add("ocrProcessingStep");
lstApprove.Add("ParagraphStyle");
lstApprove.Add("Layout");
lstApprove.Add("Page");
lstApprove.Add("PrintSpace");
lstApprove.Add("TextBlock");
lstApprove.Add("TextLine");
lstApprove.Add("String");
lstApprove.Add("SP");
lstApprove.Add("ComposedBlock");
lstApprove.Add("GraphicalElement");
and here is the code for removing the tags that are not on the list
using (StreamReader reader = new StreamReader(xmlFile))
{
nAlto = reader.ReadToEnd();
nAlto = nAlto.Replace("<document xmlns=\"http://www.scansoft.com/omnipage/xml/ssdoc-schema3.xsd\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">", "<document>");
nAlto = nAlto.Replace("<?xml version=\"1.0\" encoding=\"UTF-16\"?>", "");
}
XDocument doc = XDocument.Parse(nAlto);
foreach (var item in doc.Descendants().ToList())
{
if (!lstApprove.Contains(item.Name.ToString()))
{
if (item.HasElements)
{
item.ReplaceWith(item.Elements());
}
else
{
item.Remove();
}
}
}
and here is the output
http://pastebin.com/XjYBTWci
this is the part of xml output
<dd l="2342.29" t="133.12" r="2427.71" b="209.17">
<TextBlock ID="P1_TB0000001" TAGREFS="LAYOUT_TAG_001" HPOS="2349.17" VPOS="160" WIDTH="71.66" HEIGHT="36.04" STYLEREFS="PAR_LEFT">
<TextLine ID="P1_TL0000001" HPOS="2362.92" VPOS="160" WIDTH="44.16" HEIGHT="36.04">
<String ID="P1_ST0000001" HPOS="2362.92" VPOS="160" WIDTH="44.16" HEIGHT="36.04" CONTENT="43" />
</TextLine>
</TextBlock>
</dd>
i still have the dd tag, even if its not in my list. why? thank you
The problem is that when you replace the item with its elements the Item is removed from the xDocument and so are its children so when you try to remove any of the children of the removed element, in your case the <dd> element it is detached from your xDocument so it hasn't any effect on it. To overcome this problem you need to store the parent of the Element you are removing and then iterate recursively over its children
public static void RemoveRecursive(XElement current, List<string> goodNames)
{
var parent = current;
if (!goodNames.Contains(current.Name.ToString()))
{
parent = current.Parent;
current.ReplaceWith(current.Elements());
}
foreach (var element in parent.Elements())
{
RemoveRecursive(element, goodNames);
}
}
try this function where current is doc.Root and goodNames is lstApprove
I think the issue with your code is you are missing the closing forward slash on "/document" in the replace. The code below works
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
List<string> lstApprove = new List<string>() {
"Styles", "alto", "Description", "MeasurementUnit",
"sourceImageInformation",
"fileName", "OCRProcessing", "preProcessingStep",
"processingSoftware", "softwareCreator", "softwareName",
"softwareVersion", "ocrProcessingStep", "ParagraphStyle",
"Layout", "Page", "PrintSpace", "TextBlock",
"TextLine", "String", "SP", "ComposedBlock", "GraphicalElement"
};
XDocument doc = XDocument.Load(FILENAME);
List<XElement> elements = doc.Descendants().Where(x => lstApprove.Contains(x.Name.LocalName)).ToList();
string xml = "<?xml version=\"1.0\" encoding=\"UTF-16\"?>" +
"<document xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"></document>";
XDocument newDoc = XDocument.Parse(xml);
XElement document = (XElement)newDoc.FirstNode;
document.Add(elements);
}
}
}
Related
I need your help to finish my task also gain some knowledge from it.
I am having XMl like below
<?xml version="1.0" encoding="UTF-8"?>
<spml:batchRequest xmlns:subscriber="urn:abc:names:prov:gw:SUBSCRIBER:3:0" xmlns:spml="urn:abc:names:prov:gw:SPML:2:0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" execution="synchronous" timestamp="true" processing="sequential" onError="exit_commit">
<version>SUBSCRIBER_v30</version>
<request xsi:type="spml:ModifyRequest" returnResultingObject="full">
<version>SUBSCRIBER_v30</version>
<objectclass>Subscriber</objectclass>
<identifier>1234567890</identifier>
<modification name="udm5gData/servingPlmnId[#plmnId='20201']/provisionedData/sessionManagementSubscriptionData[#singleNssai='1-000002']/dnnConfiguration[#dnnId='dj.nmdd']" operation="remove" scope="uniqueTypeMapping" xmlns:subscriber="urn:abc:names:prov:gw:SUBSCRIBER:3:0">
</modification>
</request>
</spml:batchRequest>
Out of this I need to modify the #singleNssai='1-000002' from modification tag Could anyone help me to change.
Something like #singleNssai='2-000001'
I am trying like below
XmlDataDocument doc = new XmlDataDocument();
doc.Load("D:\\soaptemp\\test.xml");
XmlNode singlenssais =
doc.SelectSingleNode("//modification/name/#singleNssai");
if (singlenssais != null)
{
singlenssais.Value = "2-000001"; // Set to new value.
}
Using Xml Linq
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication40
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
XElement modification = doc.Descendants("modification").First();
XAttribute name = modification.Attribute("name");
string strName = (string)name;
strName = strName.Replace("1-000002", "2-000001");
name.SetValue(strName);
}
}
}
I have console app which i am trying to automate , there is manual process to remove headers and footer tags form .trg file . Can anyone suggest how to remove headers and footers using c sharp.
Header looks like this.
<Batch remotefolder="\\srv-dg-procl13\nexdox\nxtil04\process\200863-142325x-mkts\output\archive\absamples_pims_pdf\" grid="200863-142325X-MKTS" streamID="ABSAMPLES_PIMS_PDF" delivertobox="False">
<Application application="NXTIL04" name="Mifid 10 percent drop Notification " output="ABSAMPLES_PIMS_PDF">
<Indexes>
<Index name="Reference" description="Reference" type="StringDefinition" visible="True" />
</Indexes>
</Application>
footer looks like this .
</Batch>
This is what i am trying to do but not working .
private void RemoveHeader(string Xlfile)
{
XmlDocument doc = new XmlDocument();
doc.Load(Xlfile);
foreach (XmlNode node in doc.SelectSingleNode("Batch"))
{
doc.RemoveAll();
}
}
XPath is your friend here.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
namespace testconsole
{
class Program
{
public static string strFileName = "c:\\temp\\test.xml";
static void Main(string[] args) {
XmlDocument xml = new XmlDocument();
xml.Load(strFileName);
XmlElement ndMatch = (XmlElement)xml.SelectSingleNode("//Application");
if (ndMatch != null) {
XmlDocument xmlNew = new XmlDocument();
xmlNew.LoadXml(ndMatch.OuterXml);
xmlNew.Save(strFileName + ".new");
} else {
Console.Write("Cannot load " + strFileName);
}
}
}
}
I'm Trying to Delete a node from XML with C#, but for some reason I can't.
What I doing wrong?
The code runs well, respond with true, but the XML don't change and the node is not eliminated.
This is my code to Delete:
internal static bool DeleteCamera(string name)
{
XmlDocument xml = new XmlDocument();
xml.Load("xmlpath.xml");
XmlNode toDelete = xml.SelectSingleNode("//Camera[#Name='" + name + "']");
if (toDelete == null)
{
return false;
}
else
{
toDelete.ParentNode.RemoveChild(toDelete);
xml.Save("xmlpath.xml");
return true;
}
}
This is my XML result with WCF service:
<Cameras>
<Camera Name="Camara1" Url="Camara1" Width="600" Height="800" />
<Camera Name="Camara2" Url="Camara2" Width="600" Height="800" />
</Cameras>
Thank you guys, the problem was the containing apostrophe (?) before and after name string.
XmlNode toDelete = xml.SelectSingleNode("//Camera[#Name='" +name+ "']");
But I don't know why I need to restart the service to see the changes if I have a Method to load the xml file.
Use xml linq. The name in xml is "Camara1" not "Camera1".
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
string removeName = "Camara1";
XElement camera = doc.Descendants().Where(x => (x.Name.LocalName == "Camera") && ((string)x.Attribute("Name") == removeName)).FirstOrDefault();
camera.Remove();
}
}
}
I've been at this for a few hours now and was hoping someone could point me in the right direction.
my psuedo xml file:
<Parent>
<child Seq="1">
<Num1>1137555</Num1>
</Child>
<Child2>
<Text1>random text</Text1>
</Child2>
</Parent>
I'm trying to get a reference to the Elements Name(in this case "Num1") and it's value("1137555"). I understand that the reader will read Num1 first, and then the content but my code seems to be skipping over a large chunk of my xml. I have about 16 different child elements nested in the parent element but i'm only getting back perhaps the last half of them.
My Code:
while (xmlReader.Read())
{
if (xmlReader.NodeType == XmlNodeType.Element)
{
Console.WriteLine(xmlReader.Name);
}
if (xmlReader.HasValue)
{
Console.WriteLine(xmlReader.Value);
}
}
1) I would suggest to take a look at XDocument.
2) There is an error in your XML structure your first Child node is invalid.
<child></Child> (the first c is not in capital case)
Here is my code using XDocument:
var xml = "<Parent><Child Seq='1'><Num1>1137555</Num1></Child><Child2><Text1>random text</Text1></Child2></Parent>";
var document = XDocument.Parse(xml);
foreach (var child in document.Root.Elements("Child"))
{
child.Element("Num1").Value.Dump();
}
Output:
Try a combination of XmlReader and Xml linq
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XmlReader reader = XmlReader.Create(FILENAME);
while (!reader.EOF)
{
if (reader.Name != "Parent")
{
reader.ReadToFollowing("Parent");
}
if (!reader.EOF)
{
XElement parent = (XElement)XDocument.ReadFrom(reader);
foreach (XElement child in parent.Elements())
{
XElement grandchild = child.Elements().FirstOrDefault();
Console.WriteLine("tag : '{0}', value : '{1}'", grandchild.Name.LocalName, (string)grandchild);
}
}
}
Console.ReadLine();
}
}
}
My problem is simple. I'm using XPath to retrieve information from a xml file. My goal is to compare 2 XML files, they should be the same. I have no problem with "single" nodes. My problem comes when there are siblings.
It looks like that :
XPathDocument expectedDocument = new XPathDocument("C:\\expected.xml");
XPathDocument testedDocument = new XPathDocument("C:\\tested.xml");
XPathNavigator expectedNav = expectedDocument.CreateNavigator();
XPathNavigator testedNav = testedDocument.CreateNavigator();
XPathNodeIterator expectedIterator;
XPathNodeIterator testedIterator;
string expectedStr;
string testedStr;
string parameter;
parameter = "/DonneesDepot/Identification/#CoclicoFacturation";
expectedStr = expectedNav.SelectSingleNode(parameter).Value;
testedStr = testedNav.SelectSingleNode(parameter).Value;
CompareValues(expectedStr, testedStr, parameter);
That works perfectly. Now where it gets complicated is for this kind of XML :
<Surtaxe>
<Zone CodeZoneSurtaxe="1" NbPlisZone="0" PoidsZone="0" />
<Zone CodeZoneSurtaxe="2" NbPlisZone="2" PoidsZone="2" />
</Surtaxe>
I want to be able to make sure the content of "Surtaxe" is the same in both files (keep in mind the order is not important), so I tried this :
parameter = "/DonneesDepot/Facturation/Surtaxe/Zone/#PoidsZone";
expectedIterator = expectedNav.Select(parameter);
testedIterator = testedNav.Select(parameter);
while (expectedIterator.MoveNext() && testedIterator.MoveNext())
{
CompareValues(expectedIterator.Current.Value, testedIterator.Current.Value, parameter);
}
But even if the XMLs both contain the two rows, they are sometimes not in the same order, so my while loop doesn't work.
What would be the easiest to compare the two followings (the expected result of this comparison would be "Equality")
<Surtaxe>
<Zone CodeZoneSurtaxe="1" NbPlisZone="1" PoidsZone="1" />
<Zone CodeZoneSurtaxe="2" NbPlisZone="0" PoidsZone="0" />
</Surtaxe>
and
<Surtaxe>
<Zone CodeZoneSurtaxe="2" NbPlisZone="0" PoidsZone="0" />
<Zone CodeZoneSurtaxe="1" NbPlisZone="1" PoidsZone="1" />
</Surtaxe>
Thank you
This will do what you want, you may need to change it up for your real objects, but this should get you started. I proveded 2 solutions. A naive n^2 solution and a sorting method that should be faster.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace XmlCompare
{
using System.IO;
using System.Xml.Linq;
using System.Xml.XPath;
class Program
{
private static string xml1 = "<Surtaxe>" + "<Zone CodeZoneSurtaxe=\"2\" NbPlisZone=\"0\" PoidsZone=\"0\" />"
+ "<Zone CodeZoneSurtaxe=\"1\" NbPlisZone=\"1\" PoidsZone=\"1\" />" + "</Surtaxe>";
private static string xml2 = "<Surtaxe>" + "<Zone CodeZoneSurtaxe=\"1\" NbPlisZone=\"1\" PoidsZone=\"1\" />"
+ "<Zone CodeZoneSurtaxe=\"2\" NbPlisZone=\"0\" PoidsZone=\"0\" />" + "</Surtaxe>";
private static void Main(string[] args)
{
var expectedDoc = XDocument.Load(new StringReader(xml1));
var testedDoc = XDocument.Load(new StringReader(xml2));
var success = true;
//naive
foreach (var node in expectedDoc.Descendants("Surtaxe").First().Descendants())
{
if (testedDoc.Descendants(node.Name).FirstOrDefault(x => x.ToString()== node.ToString()) == null)
{
success = false;
break;
}
}
//sort
var sortedExpected = xml1.ToList();
sortedExpected.Sort();
var testSorted = xml2.ToList();
testSorted.Sort();
success = new string(sortedExpected.ToArray()).Equals(new string(testSorted.ToArray()));
Console.WriteLine("Match? " + success);
Console.ReadKey();
}
}
}