2009-09-17 87 views
4

当我将一个XML文档从磁盘加载到XDocument中时,该XDocument具有仅包含原始XML文档在磁盘上的位置的就绪属性BaseUri。换句话说,我可以将BaseUri分配给XDocument吗?

XDocument doc = XDocument.Load(@"c:\temp\doc.xml"); 
Console.Out.WriteLine(doc.BaseUri); 
// Outputs "file:///c:/temp/doc.xml" 

如果我从头开始创建一个新的XDocument,它没有BaseUri。例如:

XDocument doc = new XDocument(new XElement("test")); 
Console.Out.WriteLine(doc.BaseUri); 
// Outputs nothing 

我可以为这个新的XDocument分配一个BaseUri吗?我希望能够生成新文档,为其分配名称,并轻松将这些名称与它们一起传递。

回答

2

在阅读LoadOptions.SetBaseUri之后,很明显LINQ to XML使用Annotations来实现BaseUri属性的设置。这很不幸,因为注释的内部类型为System.Xml.Linq.BaseUriAnnotation,您无法访问它。我的建议可能是设置自己的注释,如果它不是null,它将使用其值或BaseUri的值。

public class MyBaseUriAnnotation 
{ 
    public XObject XObject { get; private set; } 

    private string baseUri = String.Empty; 
    public string BaseUri 
    { 
     get 
     { 
      if (String.IsNullOrEmpty(this.baseUri)) 
       return this.XObject.BaseUri; 

      return this.baseUri; 
     } 

     set { this.baseUri = value; } 
    } 

    public MyBaseUriAnnotation(XObject xobject) 
     : this(xobject, String.Empty) 
    { 
    } 

    public MyBaseUriAnnotation(XObject xobject, string baseUri) 
    { 
     if (xobject == null) throw new ArgumentNullException("xobject"); 
     this.XObject = xobject; 
     this.baseUri = baseUri; 
    } 
} 

然后,您可以使用一种方法来添加注释到XDocument你对自己的分析:

public static XDocument XDocumentFromString(string baseUri, string xml) 
{ 
    var xdoc = XDocument.Parse(xml); 
    xdoc.AddAnnotation(new MyBaseUriAnnotation(xdoc, baseUri)); 
    return xdoc; 
} 

然后只要你想找到的BaseUri,你可以使用一个扩展方法来获取正确的BaseUri

public static string FindBaseUri(this XObject xobject) 
{ 
    if (xobject == null) throw new ArgumentNullException(xobject); 
    var baseUri = xobject.Annotation<MyBaseUriAnnotation>(); 
    return baseUri != null ? baseUri.BaseUri : xobject.BaseUri; 
} 
+0

谢谢,我没有想过用注释的 – 2009-09-17 20:02:08

+0

您还可以延长我的例子,搜索起来。 XObject层次结构,直到找到MyBaseUriAnnotation以便与XObject.BaseUri的行为相同。 – user7116 2009-09-17 20:25:58

3

据我所知,你不能轻易这样做。如果您设置了适当的选项,您可以在装入任何XmlReader时执行此操作。这意味着你可以写一个扩展方法,将其保存到MemoryStream,然后从XmlTextReader派生的自定义类中加载一个新文档,该文档覆盖了BaseUri。这将是很丑陋,但:(

+0

但它起作用:/(对于XmlDocument也是如此)。 – 2014-11-04 09:37:30

1

丑陋的,但最快的方法:

var doc = XElement.Parse(someXml); 
doc.GetType() 
     .GetMethod("SetBaseUri", BindingFlags.NonPublic | BindingFlags.Instance) 
     .Invoke(doc, new object[] { "some uri" }); 
0
public class CustomXmlDocument : XmlDocument 
    { 
     public string CustomBaseURL { get; set; } 


     public override string BaseURI 
     { 
      get { return this.CustomBaseURL; } 
     } 
    } 

CustomXmlDocument objXML=new CustomXmlDocument(); 
objXML.CustomBaseURL="BaseURI"; 
objXML.loadXml(xml document); 
相关问题