我可以将BaseUri分配给XDocument吗?

时间:2009-09-17 16:48:34

标签: c# xml linq-to-xml

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

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吗?我希望能够生成新文档,为它们分配名称,并轻松地将这些名称与它们一起传递。

4 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:3)

丑陋但最快的方式:

var doc = XElement.Parse(someXml);
doc.GetType()
         .GetMethod("SetBaseUri", BindingFlags.NonPublic | BindingFlags.Instance)
         .Invoke(doc, new object[] { "some uri" });

答案 2 :(得分:2)

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

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;
}

答案 3 :(得分: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);