Replace the image in a JPG image file but keep the metadata? - c#

Is it possible to replace the image portion of a JPG but keep the embedded metadata? Alternatively, is there a way to reliably copy all metadata from one JPG image to another?
Background: I have an ASP.NET web application that stores JPG images. Users use the tinyMCE image editor to edit the image in the browser (resize, crop, etc), then the browser sends this modified image up to the server. I need to replace the original image file with the edited one while preserving the original metadata.
My first approach was to copy the System.Drawing.Imaging.PropertyItems and also copy some items using InPlaceBitmapMetadataWriter, but many properties are getting missed with this approach. I need something more reliable and it occurred to me if I could just replace the image portion that might be the ticket. But googling hasn't revealed anything.
This is an open source product (Gallery Server) so any libraries have to be compatible with this license.

You can do this with ImageMagick - here is one way.
Load the original image with the metadata you want to preserve, then load the "fake" image and composite that over the top of the original and save, and ImageMagick will preserve the original image's metadata. Let's do an example.
Here is an original image, let's check the metadata with jhead
jhead original.jpg
File name : original.jpg
File size : 2080473 bytes
File date : 2015:12:18 09:05:53
Camera make : Apple
Camera model : iPhone 4S
Date/Time : 2014:12:25 15:02:27
Resolution : 3264 x 2448
Flash used : No
Focal length : 4.3mm (35mm equivalent: 35mm)
Exposure time: 0.0083 s (1/120)
Aperture : f/2.4
ISO equiv. : 50
Whitebalance : Auto
Metering Mode: pattern
Exposure : program (auto)
GPS Latitude : N 54d 26m 14.84s
GPS Longitude: W 3d 5m 49.91s
GPS Altitude : 226.00m
JPEG Quality : 95
Now, we run the process I suggested, compositing a grey (fake) image of the same size over the top:
convert original.jpg fake.jpg -composite new.jpg
and we get this:
And if we check the metadata of the new image:
jhead new.jpg
File name : new.jpg
File size : 43408 bytes
File date : 2015:12:18 09:08:30
Camera make : Apple
Camera model : iPhone 4S
Date/Time : 2014:12:25 15:02:27
Resolution : 3264 x 2448
Color/bw : Black and white
Flash used : No
Focal length : 4.3mm (35mm equivalent: 35mm)
Exposure time: 0.0083 s (1/120)
Aperture : f/2.4
ISO equiv. : 50
Whitebalance : Auto
Metering Mode: pattern
Exposure : program (auto)
GPS Latitude : N 54d 26m 14.84s
GPS Longitude: W 3d 5m 49.91s
GPS Altitude : 226.00m
JPEG Quality : 96
... and suddenly the grey rectangle I just made two minutes ago on my Mac was taken on Christmas Day last year at exactly the same spot as the original in the Lake District :-)
If your fake image and original differ in size, you can do this to force them to a common size before compositing (so that the fake completely covers the original) like this:
convert original.jpg fake.jpg -resize 3264x2446! -composite new.jpg

For copying metadata between images. You can use exiftool, which is designed for metadata manipulation.
exiftool -TagsFromFile sourceImg.jpg target.jpg
-TagsFromFile means you are copying metadata.
add -overwrite_original before -TagsFromFile if you dont want exiftool to generate backup files.
If you want to copy selected tags or perform recursion, see this answer.

I think that ImageMagick can help you.
I saw that ImageMagick example where you can see how to extract all metadata from a jpg file.
Now if you have the metadata of the original file, you can create a new file with that metadata. I found a example of how to add metadata with ImageMagick
I hope this can help you

Related

Saving Bigger Files with TTS Android

Recently i used android TTS - I save the file as MP3 and play it using MediaPlayer so users can pause/resume etc.
It all works fine other than when i have a large text it just does not work.
I read that the android TTS has the limit of 4000 CHs? What should i do to tackle large amount of text?
The following is the code i am using to save MP3
Android.Speech.Tts.TextToSpeech textToSpeech;
...
textToSpeech = new Android.Speech.Tts.TextToSpeech(this, this, "com.google.android.tts");
...
textToSpeech.SynthesizeToFile(ReadableText, null, new Java.IO.File(System.IO.Path.Combine(documentsPath, ID + "_audio.mp3")), ID);
The following is the code i am using to playback the audio
MediaPlayer MP = new MediaPlayer();
...
MP.SetDataSource(System.IO.Path.Combine(documentsPath, ID + "_audio.mp3"));
MP.Prepare();
MP.Start();
It works for small amount of text but not for large text.
File gets saved (most likely just a corrupt file) because when i play it i get the following error
setDataSoruceFD failed: status=0x80000000
Java Solution is also acceptable
FYI - The question is about the max text size as I can generate the file for smaller text
Cheers
In Android ASOP (at least since API-18), TextToSpeech.MaxSpeechInputLength is set to 4000.
Note: OEMs could change this value in their OS image, so it would be wise to check the value and not make any assumptions.
Note: You are naming the output with an .mp3 extension, but by default the files created will be .wav formatted, some speech engines do support other formats/bitrate/etc. but you are passing null for the parameters.
Unless you want to deal with properly joining multiple wave files, I would recommend that you break your text into smaller parts and synthesize multiple files.
You can then play these back in sequence (using the MediaPlayer Completion event|listener).

How can I obtain the CRC from a CAN(Controller Area Network) message frame?

I have a project in which I need to create a perl script to parse a .hex file into a .can file full of CAN frames for to be sent. Once the file has been parsed it is going to be read by a C# based GUI that will translate those lines into proper CAN messages to be sent.
The list of aspects that I need to include for the .can is the following:
Add delays to TX commands
Add comments that the parser will ignore
Add a file header comment that the parser will ignore
When file was create, which file, parser version… etc.
Add a CRC (on the file itself)
Add an Application CRC (written to certain Flash memory location)
This is an example of the .hex file that I am parsing:
:020000040000FA
:10000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00
:10001000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0
:10002000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0
:10003000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD0
:10004000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0
:10005000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB0
:10006000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA0
:10007000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF90
:10008000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80
:10009000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70
Out of this list I am only missing number 4 and 5. I've been reading about what is CRC and how to make use of it, so I have some knowledge on the topic, but I do not know to implement points 4 and 5. I would appreciate some guidance on how to approach this issue. Below a sample of the .can file that I cam using:
//File used: app1FULL.hex
//Parser version: 0.2 alpha
//Date: Thu Oct 13 16:47:55 2016
TX:10:1537:8:45:EF:0B:F0:FF:FF:FF:FF //load flash
TX:10:1538:8:FA:CF:11:F0:FB:CF:12:F0 //load flash
TX:10:1539:8:E9:CF:13:F0:EA:CF:14:F0 //load flash
TX:10:1540:8:E1:CF:15:F0:E2:CF:16:F0 //load flash
TX:10:1541:8:D9:CF:17:F0:DA:CF:18:F0 //load flash
TX:10:1542:8:F3:CF:19:F0:F4:CF:1A:F0 //load flash
TX:10:1543:8:F6:CF:1B:F0:F7:CF:1C:F0 //load flash
TX:10:1544:8:F8:CF:1D:F0:F5:CF:1E:F0 //load flash
TX:10:1536:5:B:0:16:0:40:00:00:00:00:64 //flash write
RX:1000:1535:3:B:0:16:64 //expect response
PRINT:Boot has failed:Boot received all messages successfully
Thank you guys!

canon SDk Article by Johannes Bildstein

In Canon SDK sample, how can I take a photo with certain resolution such as 200-300 dpi or change the resolution programmatically, and save the taken photo in another file type, here I need to save in .TIF format? I can't find any function to do it.
author of the article here.
you can change the image resolution by setting the PropID_ImageQuality with one of the ImageQuality enums. Note that not every camera supports every enum value and the actual image resolution depends on the camera and sensor. If you need a pixel-exact image you'll have to resize it yourself.
Also, the image you download from the camera is not modified by the SDK so you can only get the image format that the camera has, usually CR2 and/or Jpg.
To get a tif from a raw file you can use the SDKs image methods. To create a raw image use the EdsCreateImageRef method and to save it use the EdsSaveImage method. As a target you can use EdsTargetImageType.TIFF (or TIFF16 for 16bit per channel).
EDIT:
quick sample for saving an image to tiff (not tested):
IntPtr imgRef;
//Open image
IntPtr inStream;
EDSDK.EdsCreateFileStream("inFile.cr2", EdsFileCreateDisposition.OpenExisting, FileAccess.Read, out inStream);
EDSDK.EdsCreateImageRef(inStream, out imgRef);
EDSDK.EdsRelease(inStream);
//do whatever you like with imgRef now
//Save image
IntPtr outStream;
var settings = new EdsSaveImageSetting();
EDSDK.EdsCreateFileStream("outFile.tif", EdsFileCreateDisposition.CreateAlways, EdsFileAccess.Write, out outStream);
EDSDK.EdsSaveImage(imgRef, EdsTargetImageType.TIFF, settings, outStream);
EDSDK.EdsRelease(outStream);
To get a TIFF image, shoot in RAW format and after downloading the image use the EdsSaveImage function with the EdsTargetImageType set to kEdsTargetImageType_TIFF. The DPI resolution is not relevant directly, but you can always use tools like Exiftool to set the DPI explicitly.

How to capture screen to be video using C# .Net?

I know there are lots of question like this.
But I don't want to use the Windows media encoder 9 because it's a problem to get one, and then it is no longer supported.
I know that, one possibility is to capture lots of screenshots and create a video with ffmpeg but I don't want use third party executables.
Is there are a .net only solution?
the answer is the Microsoft Expression Encoder. It is according to my opinion the easiest way to record something on vista and windows 7
private void CaptureMoni()
{
try
{
Rectangle _screenRectangle = Screen.PrimaryScreen.Bounds;
_screenCaptureJob = new ScreenCaptureJob();
_screenCaptureJob.CaptureRectangle = _screenRectangle;
_screenCaptureJob.ShowFlashingBoundary = true;
_screenCaptureJob.ScreenCaptureVideoProfile.FrameRate = 20;
_screenCaptureJob.CaptureMouseCursor = true;
_screenCaptureJob.OutputScreenCaptureFileName = string.Format(#"C:\test.wmv");
if (File.Exists(_screenCaptureJob.OutputScreenCaptureFileName))
{
File.Delete(_screenCaptureJob.OutputScreenCaptureFileName);
}
_screenCaptureJob.Start();
}
catch(Exception e) { }
}
Edit Based on Comment Feedback:
A developer by the name baSSiLL has graciously shared a repository that has a screen recording c# library as well as a sample project in c# that shows how it can be used to capture the screen and mic.
Starting a screen capture using the sample code is as straight forward as:
recorder = new Recorder(_filePath,
KnownFourCCs.Codecs.X264, quality,
0, SupportedWaveFormat.WAVE_FORMAT_44S16, true, 160);
_filePath is the path of the file I'd like to save the video to.
You can pass in a variety of codecs including AVI, MotionJPEG, X264, etc. In the case of x264 I had to install the codec on my machine first but AVI works out of the box.
Quality only comes into play when using AVI or MotionJPEG. The x264 codec manages its own quality settings.
The 0 above is the audio device I'd like to use. The Default is zero.
It currently supports 2 wave formats. 44100 at 16bit either stereo or mono.
The true parameter indicates that I want the audio encoded into mp3 format. I believe this is required when choosing x264 as the uncompressed audio combined in a .mp4 file would not play back for me.
The 160 is the bitrate at which to encode the audio.
~~~~~
To stop the recording you just
recorder.Dispose();
recorder = null;
Everything is open source so you can edit the recorder class and change dimensions, frames per second, etc.
~~~~
To get up and running with this library you will need to either download or pull from the github / codeplex libraries below. You can also use NuGet:
Install-Package SharpAvi
Original Post:
Sharp AVI:
https://sharpavi.codeplex.com/
or
https://github.com/baSSiLL/SharpAvi
There is a sample project within that library that has a great screen recorder in it along with a menu for settings/etc.
I found Screna first from another answer on this StackoverFlow question but I ran into a couple issues involving getting Mp3 Lame encoder to work correctly. Screna is a wrapper for SharpAVI. I found by removing Screna and going off of SharpAvi's sample I had better luck.

Parsing large xml files to add new line between elements really slow

I have a scenario where I need to pull data out of a DB and write it out as xml. The problem is that the users want every element (DB Column) to be separated by a new line. The db table I am extracting has about 20,000 rows and has a lot of ntext columns (Table is about 3 Gig in size).
I am breaking the file up into 250 rows each so each file comes out to be around 14MB each. The problem is that the parsing is really really slow. In order to add a new line between each element/column I am adding some unique strings between each column coming out of the db so that I can use a Regex.Split function and append a new line to each item in that array.
I am sure that the slowness is user error / ignorance on my part as I live mostly in DBs, but I am not really sure what to do to try and speed up the parsing. Extracting the data as xml from the db is fast and writes rather quickly. But, introducing the parsing and adding a new line between each element has made each file write about 3 minutes per file.
Any suggestions on what I should be using in C# to parse and add the newline would be greatly appreciated.
As always I appreciate the input / comments I get on Stack.
Code I am using to parse the xml data:
//parsing the xml anywhere I see the string AddNewLine
public static void WriteFile(string xml,int fileNum)
{
string[] xmlArray = Regex.Split(xml, "AddNewLine");
string newXml = "";
//Getting filepath to write file out to
Connection filePath = new Connection();
string fileName = filePath.FilePath;
//foreach item in the array append carriage and new line
foreach(string xmlRow in xmlArray)
{
newXml = newXml + xmlRow + "\n\r\n";
}
//use StreamWriter to write file
using (StreamWriter sw = new StreamWriter(fileName + fileNum + ".xml"))
{
sw.Write(newXml);
}
//XmlDocument doc = new XmlDocument();
//doc.LoadXml(newXml);
//doc.Save(#"C:\TestFileWrite\PatentSchemaNew_" + fileNum + ".xml");
}
Example XML output where I would want a new line between each element:
<products>
<product>
<ProductID>1</ProductID>
<!--New Line-->
<Product>TestProduct1</Product>
<!--New Line-->
<ProductDescription>With the introduction of the LE820 Series, Sharp once again establishes its leadership in LCD and LED technology. In a monumental engineering breakthrough, Sharp’s proprietary QuadPixel Technology, a 4-color filter that adds yellow to the traditional RGB, enables more than a trillion colors to be displayed for the first time. A stunning new contemporary edge-light design with full-front glass proudly announces a new AQUOS direction for 2010. The proprietary AQUOS LED system comprised of the X-Gen LCD panel and UltraBrilliant LEDs enables an incredible dynamic contrast ratio of 5,000,000:1 and picture quality that is second to none. The LE820 series is very fully featured, including the addition of Netflix™ streaming video capability through the AQUOS Net™ service, along with the industry’s leading online support system, AQUOS Advantage Live. A built in media player allows for playback of music and photos via USB port.
QuadPixel Technology 4-Color Filter adds yellow to the traditional RGB sub-pixel components, enabling the display of more than a trillion colors.
Full HD 1080p (1920 x 1080) Resolution for the sharpest picture possible.
UltraBrilliant LED System includes a “double-dome” light amplifier lens and multi-fluorescents, enabling high brightness and color purity.
Full HD 1080p X-Gen LCD Panel with 10-bit processing is designed with advanced pixel control to minimize light leakage and wider aperture to let more light through.
120Hz Fine Motion Advanced for fast-motion picture quality.
Wide Viewing Angles (176°H x 176°W) Sharp's AQUOS® LCD TVs’ viewing angles are so wide, you can view the TV clearly from practically anywhere in the room.
High Brightness (450 cd/m2) AQUOS LCD TVs are very bright. You can put them virtually anywhere – even near windows, doors or other light sources – and the picture is still vivid.
AQUOS Net delivers streaming video with Netflix™, customized Internet content and live customer support via Ethernet, viewable in widget, full-screen or split-screen mode.
USB Media Player adds the convenience of viewing high-resolution photos and music on the TV.</ProductDescription>
<!--New Line-->
<ProductAccessories> What You'll Need
Add
Monster Cable MC BNDLF OL150F Bundle HDTV Performance Kit with Flat Panel Wall Bracket
Monster Cable HT700 8 Outlet Surge Protector
Monster's SurgeGuard™ protects components from harmful surges and...
$208.95
Get More Performance
Add
AudioQuest AQ Kit4 1-4ft. and 1-8ft. Black HDTV Performance Pack with HDMI Cables, Screen Cleaner & Mitt
Uncompressed digital signal for the highest quality picture and sound. One cable for video, audio and control. Two-way communication for expanded system control. Automatic display and source matching for resolution, format and aspect ratio. Computer and gaming compatibility. $79.75
Recommended Accessories
General Accessory
Add
Monster Cable ScreenClean 6oz. Ultimate Performance TV Screen Cleaner
Safe for use on your iPad, iPhone, iPod Touch, laptops, monitors, and TV screens Includes a high-tech reusable MicroFiber cloth that cleans screens without scratching Powerful cleaning solution removes dust, dirt, and oily fingerprints for ultimate clarity Advanced formula cleans without dripping, streaking, or staining like ordinary cleaners $13.94
Add
AudioQuest CleanScreen TV Screen Cleaning Kit
$19.75
Protection Plans
Add
TechShield TTL200S5 5-Year Service Warranty for LCD TVs $1,000-$2,000 (In-Home Service)
Parts and labor coverage with no deductibles No-lemon guarantee 50% value guarantee if you never use the warranty service $314.95
Add
TechShield TTL200S3 3-Year Service Warranty for LCD TVs $1,000-$2,000 (In-Home Service)
$157.95
Add
TechShield TTL200S4 4-Year Service Warranty for LCD TVs $1,000-$2,000 (In-Home Service)
$262.95
Add
TechShield TTL200S2 2-Year Service Warranty for LCD TVs $1,000-$2,000 (In-Home Service)
$104.95
Flat Panel Wall Mount - Fixed
Add
OmniMount OL150F Flat Panel Wall Bracket
Eco-friendly design and packaging Low mounting profile Includes universal rails and spacers for greater panel compatibility Small footprint provides ample room for power and A/V cutouts behind panel Lift n’ Lock™ allows you to easily attach your flat panel to the mount Sliding lateral on-wall adjustment Locking system secures panel to mount Installation template for simple and accurate mounting Includes end caps for a clean side view Includes complete hardware kit $99.95
Add
OmniMount NC200F Black Fixed Wall Mount for 37-63 inch Flat Panels
$129.95
Flat Panel Wall Mount - Tilt
Add
OmniMount NC200T Black Tilt Mount for 37-63 inch Flat Panels
Universal rails for greater panel compatibility Sliding lateral on-wall adjustment Locking bar works with padlock or screw End caps cover locking hardware and present a clean side view Installation template for simple and accurate mounting $179.95
Flat Panel Wall Mount - Cantilever/Articulating
Add
OmniMount UCL-X Platinum Wishbone Cantilever Mount Heavy Duty Dual Arm Double Stud
Tilt, pan and swivel for maximum viewing flexibility Weight capacity: 200 lbs Double-arm i-beam design for added strength Integrated cable management hides wires Lift and lock mounting system $279.88
Add
OmniMount NC125C Black Cantilever Mount for 37-52 inch Flat Panels
$299.95
Line Conditioner/Surge Protector
Add
Panamax PM8-GAV Surge Protector with Current Sense Control
8 Outlets (4 switched, 4 always on) Exclusive Protect or Disconnect circuitry Telephone line protection Cable and Satellite protection $59.89
Add
Monster Cable DL MDP 900 Monster Digital PowerCenter MDP 900 w/ Green Power and USB Charging
$74.77
HDMI Cable
Add
AudioQuest HDMI-X 2m (6.56 ft) HDMI Digital Audio Video Cable with Braided Jacket
Large 1.25% silver conductors Critical Twist Geometry Solid High-Density Polyethylene is used to minimize loss caused by insulation Uncompressed digital signal for the highest quality picture and sound $40.00
Add
Icarus ECB-HDM2 2m (6.56 ft) HDMI Digital Audio Video Cable
$16.95
Add
Monster Cable MC HDMIB 2m (6.56 ft.) HDMI Cable
$39.00
Component Video Cable
Add
Monster Cable MC 400CV-2m (6.56 ft.) Advanced Performance Component Video Cable
Get All the High Resolution Picture You Paid For
Your new DVD player, cable/satellite receiver, and TV might be more advanced... $49.00
Add
Monster Cable MC 400CV-1m (3.28 ft.) Advanced Performance Component Video Cable
$39.00
Add
AudioQuest YIQ-A 2m (6.6 ft) Component Video Cable
$44.75
General Accessory
Add
Monster Cable ScreenClean 6oz. Ultimate Performance TV Screen Cleaner
Safe for use on your iPad, iPhone, iPod Touch, laptops, monitors, and TV screens Includes a high-tech reusable MicroFiber cloth that cleans screens without scratching Powerful cleaning solution removes dust, dirt, and oily fingerprints for ultimate clarity Advanced formula cleans without dripping, streaking, or staining like ordinary cleaners $13.94
Add
AudioQuest CleanScreen TV Screen Cleaning Kit
$19.75</ProductAccessories>
<ProductFeatures>Detailed Specifications:
Basic Specifications
10-bit LCD Panel Yes
120HzFrameRate Yes
Aspect Ratio 16:09
Audio System 10W + 10W +15W (Subwoofer)
Backlight System Edge LED
Panel Type X-Gen LCD Panel
Pixel Resolution 1920 x 1080 (x4 sub-pixels) 8 million dots
Response Time 4ms
Tuning System ATSC / QAM / NTSC
Viewing Angles 176° H / 176° V Features
AQUOS Net Yes
AQUOS AdvantageSM Support Yes
AQUOS® Series Yes
Digital Still Picture Display Yes
Quattron quad pixel technology Yes
Included Accessories
Remote Control Yes
Table Stand Yes Power
Power Consumption AC (watts) 160W
Power Source 120 V, 60 Hz
Terminals
Audio Inputs (L/R) RCA X 2
Composite Video 1
Ethernet Input 1
HD Component 1
HDMI® 4
PC 1 (15-pin D-sub)
RS-232C 1
Weight & Dimensions Dimensions
Dimensions (wxhxd) (inches) 49-39/64" x 31-59/64" x 1-37/64
Dimensions with Stand(wxhxd) (inches) 49-39/64" x 33-57/64" x 13-25/64" Weight
Product Weight (lbs.) 66.1
Weight with Stand & Speakers (lbs.) 79.4</ProductFeatures>
<!--New Line-->
<CreatedDate>2011-03-13T12:59:54.627</CreatedDate>
<!--New Line-->
<LastModifiedDate>2011-03-13T12:59:54.627</LastModifiedDate>
<!--New Line-->
</product>
</products>
Thanks,
S
If I understand correctly the question and you have already AddNewLine separator in you input 14 MB XML files, possible you don't need load all file and split into parts at all. - Just read from input file line by line, replace AddNewLine text with new line in each line, where the separator exists and write modified line to new output file.
Following code will replace your AddNewLine text with \n\r\n in several orders faster than your function - less then 1 sec.
using (var streamOut = new StreamWriter(outputFileName)
{
using (var streamIn = new StreamReader(inputFileName)
{
while (!streamIn.EndOfStream)
{
string line = streamIn.ReadLine();
line = line.Replace("AddNewLine", "\n\r\n");
streamOut.WriteLine(line);
}
}
}
I think that you should investigate vtd-xml for at least three reasons:
Parsing performance and memory usage
Incremental update: DOM's problem is that it will construct a tree by taking apart the input document, then write the whole thing back out by concatnation. VTD-XML doesn't take apart the input doc, and the modification is by directly inserting the whitespace char (in your situation) into the docoument's byte representation. SAX and Pull will have the similar issue.
Support for xpath and random access.
Based on the info given above, I fully expect the performance to be below 1 sec for each file. What does your file look like? I would be glad to provide some sample code
Ok here is the code that does the white space insertion
using System;
using System.Text;
using System.Net;
using com.ximpleware;
public static void insertWS()
{
VTDGen vg = new VTDGen();
if (vg.parseFile("input.xml",false){
VTDNav vn = vg.getNav();
AutoPilot ap = new AutoPilot(vn);
XMLModifier xm = new XMLModifier(vn);
ap.selectXPath("/products/product/*");
while(ap.evalXPath()!=-1){
xm.insertAfterElement("\n");
}
xm.output("output.xml");
}
}
If I were you, I would abandon the string replace method and approach this from different angle. I would add the new lines as part of the xml when creating the xml and not after the fact. Something along the lines of:
void WriteXml(string xmlFileName, DataRowCollection rows)
{
var xmlSettings = new XmlWriterSettings { Indent = true };
using(StreamWriter stream = new StreamWriter(xmlFileName))
using(XmlWriter writer = XmlWriter.Create(stream, settings))
{
writer.WriteStartElement("products");
foreach(DataRow row in rows)
{
writer.WriteStartElement("product");
writer.WriteElementString("ProductID", row["ProductID"].ToString());
writer.Flush();
stream.WriteLine(); //insert new line
writer.WriteElementString("Product", row["Product"].ToString());
writer.Flush();
stream.WriteLine(); //insert new line
//repeat for rest of columns/elements
//...
writer.WriteEndElement(); //end product
}
writer.WriteEndElement(); //end products
}
}

Categories

Resources