468,738 Members | 1,593 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,738 developers. It's quick & easy.

Insert Doctype Node Dynamically

I am receiving xml documents from a customer without a reference to a
doctype. I know what the Doctype DTD should be need to insert the
declaration as follows

<?xml version="1.0" encoding="UTF-8"?>
<!-- start of add validation tag -->
<!DOCTYPE D1XML SYSTEM "http://url/myDTD.DTD">
<!-- end of add validation tag -->
<XML.....>

Using one of the provided framework classes such as XmlValidatingReader,
etc.... is there a method to dynamically add a doctype reference? Or do I
have to find the starting node and perform an insert to the doctype
afterwards? Bottom line is I need a foolproof way to add this doctype
reference in the right spot each time.

For all of you asking, "Why...." The customer will be adding this DTD
reference shortly, but for now this is the "band-aid" that needs to be
applied.

Thanks for your help.
Nov 12 '05 #1
1 3921
"Chris Fink" <ch********@gmail.com> wrote in message news:%2****************@TK2MSFTNGP10.phx.gbl...
I am receiving xml documents from a customer without a reference to a
doctype. I know what the Doctype DTD should be need to insert the
declaration as follows

<?xml version="1.0" encoding="UTF-8"?>
<!-- start of add validation tag -->
<!DOCTYPE D1XML SYSTEM "http://url/myDTD.DTD">
<!-- end of add validation tag -->
<XML.....>

Using one of the provided framework classes such as XmlValidatingReader,
etc.... is there a method to dynamically add a doctype reference?


While streaming it through an XmlValidatingReader, one possibility
is to subclass one of the Reader classes from the System.IO name-
space to insert the additional line(s) you seek for the reference to
an external DTD.

Here is an example of such a class that could do this (I only impl'd
the Read(char[],int,int) method because in a quick test, that's what
was used when loading an XmlDocument as you may if you wrap
this Reader in an XmlTextReader -- so your mileage may vary.)

- - - InsertLineStreamReader.cs (partial)
using System;
using System.Collections;
using System.IO;

namespace Derek.IO
{
public class InsertLineStreamReader : System.IO.StreamReader
{
private delegate int ReadMethod(char[] buffer, int index, int count);

string insertStr;
int lineNo, readNo, overflowIndex;
char[] overflow;

ReadMethod[] fnRead;

public InsertLineStreamReader(Stream source, string insertStr, int lineNo) : base( source)
{
this.insertStr = insertStr;
this.lineNo = lineNo;
this.readNo = 0;
this.fnRead = new ReadMethod[] {
new ReadMethod( this.ReadBefore),
new ReadMethod( this.ReadOverflow),
new ReadMethod( this.ReadAfter)
};
this.overflowIndex = 0;
}

//
// . . . Override other methods here (may not be necessary depending on the consumer).
//

public override int Read(char[] buffer, int index, int count)
{
// Use dispatch table of delegates to get the complex override(s)
// out of the way asap.
return this.fnRead[this.readNo](buffer, index, count);
}

public int ReadBefore(char[] buffer, int index, int count)
{
char[] scan = new char[count];
int cchRead = base.Read(scan, 0, count);
if (cchRead > -1)
{
int insOfs, lineCnt = 0;
for (insOfs = 0; insOfs < cchRead && this.lineNo != lineCnt; ++insOfs)
{
if (scan[insOfs] == '\n') ++lineCnt;
}
if (this.lineNo == lineCnt)
{
char[] insertBuf = this.insertStr.ToCharArray( );
if ((insOfs + this.insertStr.Length) > count)
{
int fragmentLen = (insOfs + insertBuf.Length - count);
Array.Copy(scan, 0, buffer, index, insOfs);
Array.Copy(insertBuf, 0, buffer, index + insOfs, fragmentLen);
this.overflow = new char[insertBuf.Length - fragmentLen];
Array.Copy(insertBuf, fragmentLen, this.overflow, 0, this.overflow.Length);
this.readNo = 1;
cchRead = count;
}
else
{
Array.Copy(scan, 0, buffer, index, insOfs);
Array.Copy(insertBuf, 0, buffer, index + insOfs, insertBuf.Length);
int destSpaceRemaining = count - insOfs - insertBuf.Length;
int srcSpaceRemaining = cchRead - insOfs;
if (srcSpaceRemaining > destSpaceRemaining)
{
Array.Copy(scan, insOfs, buffer, index + insOfs + insertBuf.Length, destSpaceRemaining);
this.overflow = new char[srcSpaceRemaining - destSpaceRemaining];
Array.Copy(scan, insOfs + destSpaceRemaining, this.overflow, 0, this.overflow.Length);
this.readNo = 1;
cchRead = count;
}
else
{
Array.Copy(scan, insOfs, buffer, index + insOfs + insertBuf.Length, srcSpaceRemaining);
this.readNo = 2;
cchRead = cchRead + insertBuf.Length;
}
}
}
else
{
Array.Copy(scan, 0, buffer, index, cchRead);
}
}
return cchRead;
}

public int ReadOverflow(char[] buffer, int index, int count)
{
int cchRead;
int overflowLen = this.overflow.Length - this.overflowIndex;

if (count > overflowLen)
{
Array.Copy(this.overflow, this.overflowIndex, buffer, index, overflowLen);
this.overflowIndex = this.overflow.Length;
this.readNo = 2;
cchRead = overflowLen;

int nextCchRead = this.Read( buffer, index + overflowLen, count - overflowLen);
return ( -1 == nextCchRead ) ? cchRead : ( cchRead + nextCchRead );
}

Array.Copy(this.overflow, this.overflowIndex, buffer, index, count);
this.overflowIndex += count;
cchRead = count;
return cchRead;
}

public int ReadAfter(char[] buffer, int index, int count)
{
return base.Read(buffer, index, count);
}
}
}
- - -

Now you might use this to insert an arbitrary line into the beginning of
your XML instance document like this,

FileStream stream = new FileStream("doc.xml", FileMode.Open, FileAccess.Read);
string dtd = "<!-- Ref to your DTD can go here. -->";
InsertLineStreamReader reader = new InsertLineStreamReader(stream, dtd, 1);
XmlValidatingReader xmlReader = new XmlValidatingReader(new XmlTextReader( reader));
// ... wire-up Schema and ValidationEventHandler here.
XmlDocument doc = new XmlDocument( );
doc.Load( xmlReader);

As far as the XmlValidatingReader is concerned, it will receive,

<?xml version="1.0" encoding="UTF-8" ?>
<!-- Ref to your DTD can go here. -->
<XML ... />

even though your file contained,

<?xml version="1.0" encoding="UTF-8" ?>
<XML ... />
Derek Harmon
Nov 12 '05 #2

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

1 post views Thread by Rafaela K. Azinhal | last post: by
2 posts views Thread by Beniamin Tecar | last post: by
4 posts views Thread by Jaime Stuardo | last post: by
1 post views Thread by CARIGAR | last post: by
reply views Thread by zhoujie | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.