Groups | Blog | Home
all groups > dotnet xml > september 2004 >

dotnet xml : Adding <?mso-application ...> programmatically


Victor Hadianto
9/30/2004 5:47:03 PM
Hi,

If I have an XmlDocument DOM how do I insert
<?mso-application progid="ProgId.Here"?> programmatically?


--
Victor Hadianto
http://www.synop.com/Products/SauceReader/
Victor Hadianto
9/30/2004 7:47:02 PM
[quoted text, click to view]

Thanks,

Is there a way (without using Regex) to find out if I already have the <?mso
....?> on the document?

---
Derek Harmon
9/30/2004 10:19:28 PM
[quoted text, click to view]

Given an already positioned XmlNode, you can call the XmlDocument's
CreateProcessingInstruction( ) and use InsertBefore( ), InsertAfter( )
or AppendChild( ) to place the P.I. in relation to the XmlNode. e.g.,

string progId = "ProgId.Here";

xmlDoc.InsertBefore(
xmlDoc.CreateProcessingInstruction(
"mso-application",
string.Format( "progid=\"{0}\"", progId)
),
xmlNodeToInsertBefore
);

The first 'token' after the <? is called the target of the P.I. and is the first
argument to CreateProcessingInstruction( ), any remaining text after the
target up until the ?> is the second argument. The second argument may
contain multiple 'pseudo-attributes'.


Derek Harmon

Oleg Tkachenko [MVP]
10/3/2004 9:31:57 AM
[quoted text, click to view]

XmlNode pi =
xmlDoc.SelectSingleNode("/processing-instruction('mso-application')");
if (pi != null)

--
Oleg Tkachenko [XML MVP]
Derek Harmon
10/3/2004 12:55:40 PM
[quoted text, click to view]

There are at least three ways to find out if there's a processing instruction
in an XmlDocument that is (or starts with) "mso".

1. The method Oleg already posted is to use the XPath function,
processing-instruction( ). I'll add that if you want to find all PIs
starting with "mso", you'd use the following XPath expression,

//processing-instruction()[starts-with(local-name(),'mso')]

because the local-name() of a PI in XPath corresponds to the
PI's target.

2. Enumerate the DOM nodes of the document and when you
find a node with a NodeType of XmlNodeType.ProcessingInstruction
then you can examine it's LocalName and Value properties to get it's
target and pseudo-attributes, respectively.

- - - PiDomSearch.cs (excerpt)
// . . .
public void Descend( XmlNode node)
{
if ( null != node )
{
if ( XmlNodeType.ProcessingInstruction == node.NodeType )
{
if ( node.LocalName.StartsWith( "mso"))
{
// ... do something here ...
}
}
this.Descend( node.FirstChild);
this.Descend( node.NextSibling);
}
return;
}
// . . .
this.Descend( xmlDoc.DocumentElement);
// . . .
- - -


3. The prior techniques may be appealing if you're already traversing
the DOM node tree of an XmlDocument, but if you want the information
a priori then I think the best method is to use a specialized XmlReader
when loading the XmlDocument that would be responsible for detecting
the presence of these processing instructions,

- - - PiReaderSearch.cs (excerpt)
using System;
using System.Collections;
using System.IO;
using System.Xml;
// . . .

/// <summary>
/// <b>XmlTextReader</b> subclass that detects the presence of processing-instructions
/// as it reads an incoming <b>TextReader</b> whose targets start with a given text string.
/// </summary>
public class ProcInstXmlTextReader : XmlTextReader
{
private string piTarget;
private ArrayList matches;
private bool listening;

public ProcInstXmlTextReader( TextReader reader, string piTarget) : base( reader)
{
this.piTarget = piTarget;
this.matches = new ArrayList( );
}

public int MatchCount
{
get
{
return matches.Count;
}
}

public override XmlNodeType NodeType
{
get
{
this.intercepting = ( XmlNodeType.ProcessingInstruction == base.NodeType );
return base.NodeType;
}
}

public override string Name
{
get
{
string tgt = base.Name;
if ( this.intercepting )
{
if ( tgt.StartsWith( this.piTarget))
{
this.matches.Add( tgt);
this.intercepting = false;
}
}
return tgt;
}
}
}
// . . .

ProcInstXmlTextReader pixtr = new ProcInstTextReader(
new StreamReader( "filename.xml"), "mso"
);
xmlDoc.Load( pixtr);
if ( pixtr.MatchesCount > 0 )
{
// Process xmlDoc knowing that mso* PIs are present.
}
else
{
// Process xmlDoc knowing that it contains no mso* PIs.
}

// . . .
- - -

These examples presume you're looking for processing instructions that
start with the leading characters, "mso" (working with Microsoft Office
XML), but they're also easily adapted to testing for equality to "mso" if
you're looking for only one specific processing instruction target.


Derek Harmon

AddThis Social Bookmark Button