我可以为XDocument分配一个BaseUri吗?

8

当我从磁盘加载XML文档到XDocument中时,该XDocument具有只读属性BaseUri,其中包含原始XML文档在磁盘上的位置。换句话说,

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个回答

4

丑陋但最快的方法:

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

1
与尝试创建双精度值(一个由您自己设置,一个由系统设置,如原始接受的答案中所示)相比,这种方法要好得多(前提是您缓存methodinfo)。当然,如果Microsoft公开了此方法,那就更好了。 - Abel

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

2
阅读了LoadOptions.SetBaseUri之后,显而易见的是,LINQ to XML使用注释来设置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;
}

谢谢,我没有想到使用注释。 - James Sulak
你也可以扩展我的示例,搜索XObject层次结构,直到找到MyBaseUriAnnotation,以便表现与XObject.BaseUri相同。 - user7116

1
 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);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接