188 lines
6.9 KiB
C#
188 lines
6.9 KiB
C#
|
//------------------------------------------------------------------------------
|
||
|
// <copyright file="XmlEntityReference.cs" company="Microsoft">
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
// </copyright>
|
||
|
// <owner current="true" primary="true">[....]</owner>
|
||
|
//------------------------------------------------------------------------------
|
||
|
|
||
|
// <code>EntityReference</code> objects may be inserted into the structure
|
||
|
// model when an entity reference is in the source document, or when the user
|
||
|
// wishes to insert an entity reference. Note that character references and
|
||
|
// references to predefined entities are considered to be expanded by the
|
||
|
// HTML or XML processor so that characters are represented by their Unicode
|
||
|
// equivalent rather than by an entity reference. Moreover, the XML
|
||
|
// processor may completely expand references to entities while building the
|
||
|
// structure model, instead of providing <code>EntityReference</code>
|
||
|
// objects. If it does provide such objects, then for a given
|
||
|
// <code>EntityReference</code> node, it may be that there is no
|
||
|
// <code>Entity</code> node representing the referenced entity; but if such
|
||
|
// an <code>Entity</code> exists, then the child list of the
|
||
|
// <code>EntityReference</code> node is the same as that of the
|
||
|
// <code>Entity</code> node. As with the <code>Entity</code> node, all
|
||
|
// descendants of the <code>EntityReference</code> are readonly.
|
||
|
// <p>The resolution of the children of the <code>EntityReference</code> (the
|
||
|
// replacement value of the referenced <code>Entity</code>) may be lazily
|
||
|
// evaluated; actions by the user (such as calling the
|
||
|
// <code>childNodes</code> method on the <code>EntityReference</code> node)
|
||
|
// are assumed to trigger the evaluation.
|
||
|
|
||
|
namespace System.Xml {
|
||
|
|
||
|
using System.Diagnostics;
|
||
|
|
||
|
// Represents an entity reference node.
|
||
|
public class XmlEntityReference : XmlLinkedNode {
|
||
|
string name;
|
||
|
XmlLinkedNode lastChild;
|
||
|
|
||
|
protected internal XmlEntityReference( string name, XmlDocument doc ) : base( doc ) {
|
||
|
if ( !doc.IsLoading ) {
|
||
|
if ( name.Length > 0 && name[0] == '#' ) {
|
||
|
throw new ArgumentException( Res.GetString( Res.Xdom_InvalidCharacter_EntityReference ) );
|
||
|
}
|
||
|
}
|
||
|
this.name = doc.NameTable.Add(name);
|
||
|
doc.fEntRefNodesPresent = true;
|
||
|
}
|
||
|
|
||
|
// Gets the name of the node.
|
||
|
public override string Name {
|
||
|
get { return name;}
|
||
|
}
|
||
|
|
||
|
// Gets the name of the node without the namespace prefix.
|
||
|
public override string LocalName {
|
||
|
get { return name;}
|
||
|
}
|
||
|
|
||
|
// Gets or sets the value of the node.
|
||
|
public override String Value {
|
||
|
get {
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
set {
|
||
|
throw new InvalidOperationException(Res.GetString(Res.Xdom_EntRef_SetVal));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Gets the type of the node.
|
||
|
public override XmlNodeType NodeType {
|
||
|
get { return XmlNodeType.EntityReference;}
|
||
|
}
|
||
|
|
||
|
// Creates a duplicate of this node.
|
||
|
public override XmlNode CloneNode(bool deep) {
|
||
|
Debug.Assert( OwnerDocument != null );
|
||
|
XmlEntityReference eref = OwnerDocument.CreateEntityReference( name );
|
||
|
return eref;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Microsoft extensions
|
||
|
//
|
||
|
|
||
|
// Gets a value indicating whether the node is read-only.
|
||
|
public override bool IsReadOnly {
|
||
|
get {
|
||
|
return true; // Make entity references readonly
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override bool IsContainer {
|
||
|
get { return true;}
|
||
|
}
|
||
|
|
||
|
internal override void SetParent( XmlNode node ) {
|
||
|
base.SetParent(node);
|
||
|
if ( LastNode == null && node != null && node != OwnerDocument ) {
|
||
|
//first time insert the entity reference into the tree, we should expand its children now
|
||
|
XmlLoader loader = new XmlLoader();
|
||
|
loader.ExpandEntityReference(this);
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override void SetParentForLoad( XmlNode node ) {
|
||
|
this.SetParent( node );
|
||
|
}
|
||
|
|
||
|
internal override XmlLinkedNode LastNode {
|
||
|
get {
|
||
|
return lastChild;
|
||
|
}
|
||
|
set { lastChild = value;}
|
||
|
}
|
||
|
|
||
|
internal override bool IsValidChildType( XmlNodeType type ) {
|
||
|
switch (type) {
|
||
|
case XmlNodeType.Element:
|
||
|
case XmlNodeType.Text:
|
||
|
case XmlNodeType.EntityReference:
|
||
|
case XmlNodeType.Comment:
|
||
|
case XmlNodeType.Whitespace:
|
||
|
case XmlNodeType.SignificantWhitespace:
|
||
|
case XmlNodeType.ProcessingInstruction:
|
||
|
case XmlNodeType.CDATA:
|
||
|
return true;
|
||
|
|
||
|
default:
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Saves the node to the specified XmlWriter.
|
||
|
public override void WriteTo(XmlWriter w) {
|
||
|
w.WriteEntityRef(name);
|
||
|
}
|
||
|
|
||
|
// Saves all the children of the node to the specified XmlWriter.
|
||
|
public override void WriteContentTo(XmlWriter w) {
|
||
|
// -- eventually will the fix. commented out waiting for finalizing on the issue.
|
||
|
foreach( XmlNode n in this ) {
|
||
|
n.WriteTo( w );
|
||
|
} //still use the old code to generate the output
|
||
|
/*
|
||
|
foreach( XmlNode n in this ) {
|
||
|
if ( n.NodeType != XmlNodeType.EntityReference )
|
||
|
n.WriteTo( w );
|
||
|
else
|
||
|
n.WriteContentTo( w );
|
||
|
}*/
|
||
|
}
|
||
|
|
||
|
public override String BaseURI {
|
||
|
get {
|
||
|
return OwnerDocument.BaseURI;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private string ConstructBaseURI( string baseURI, string systemId ) {
|
||
|
if ( baseURI == null )
|
||
|
return systemId;
|
||
|
int nCount = baseURI.LastIndexOf('/')+1;
|
||
|
string buf = baseURI;
|
||
|
if ( nCount > 0 && nCount < baseURI.Length )
|
||
|
buf = baseURI.Substring(0, nCount);
|
||
|
else if ( nCount == 0 )
|
||
|
buf = buf + "\\";
|
||
|
return (buf + systemId.Replace('\\', '/'));
|
||
|
}
|
||
|
|
||
|
//childrenBaseURI returns where the entity reference node's children come from
|
||
|
internal String ChildBaseURI {
|
||
|
get {
|
||
|
//get the associate entity and return its baseUri
|
||
|
XmlEntity ent = OwnerDocument.GetEntityNode( name );
|
||
|
if ( ent != null ) {
|
||
|
if ( ent.SystemId != null && ent.SystemId.Length > 0 )
|
||
|
return ConstructBaseURI(ent.BaseURI, ent.SystemId);
|
||
|
else
|
||
|
return ent.BaseURI;
|
||
|
}
|
||
|
return String.Empty;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|