【问题标题】:Can I assign a BaseUri to an XDocument?我可以将 BaseUri 分配给 XDocument 吗?
【发布时间】:2010-11-29 05:28:45
【问题描述】:

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

【问题讨论】:

    标签: c# xml linq-to-xml


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      丑陋但最快的方法:

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

      【讨论】:

      • 与尝试创建一个双精度值(一个由您自己设置,一个由系统设置,如原始接受的答案)相比,这要好得多(前提是您缓存了方法信息)。当然,如果微软公开这个方法就更好了。
      【解决方案3】:

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

      【讨论】:

      • 谢谢,我没想过使用注释。
      • 您还可以扩展我的示例以向上搜索 XObject 层次结构,直到找到 MyBaseUriAnnotation 以便与 XObject.BaseUri 具有相同的行为。
      【解决方案4】:
       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);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-12-28
        • 2015-01-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多