【问题标题】:How to convert XmlNode into XElement?如何将 XmlNode 转换为 XElement?
【发布时间】:2014-07-14 19:05:56
【问题描述】:

我有一个旧的基于XmlNode 的代码。但解决我当前任务的最简单方法是使用XElement 和 LINQ-to-XML。唯一的问题是在 .NET Framework 中没有直接或明显的方法可以将 XmlNode 转换为 XElement

所以对于初学者,我想实现一个接收XmlNode 实例并将其转换为XElement 实例的方法。

如何实现这种转换?

【问题讨论】:

  • 您的所有XmlNode 实例都是XmlElement 实例吗?
  • @JohnSaunders 是的,所有XmlNode 实例都是XmlElement 实例。
  • @JohnSaunders,抱歉,并非所有 XmlNode 实例都是 XmlElement 实例。例如,它们可能是 XmlComment 实例。

标签: c# .net linq linq-to-xml


【解决方案1】:
var xElem = XElement.Load( xmlElement.CreateNavigator().ReadSubtree() );

在其他答案中使用 xmlElement.InnerXml 有两个问题,

1-你会松开root元素(当然可以轻松搞定)

XmlDocument doc = new XmlDocument();
doc.LoadXml("<root> <sub>aaa</sub> </root>");
var xElem1 = XElement.Load(doc.DocumentElement.CreateNavigator().ReadSubtree());
var xElem2 = XElement.Parse(doc.DocumentElement.InnerXml);

xElem2 将是&lt;sub&gt;aaa&lt;/sub&gt;,没有(root

2-如果您的 xml 包含文本节点,您将得到异常

XmlDocument doc = new XmlDocument();
doc.LoadXml("<root> text <sub>aaa</sub> </root>");
var xElem1 = XElement.Load(doc.DocumentElement.CreateNavigator().ReadSubtree());
var xElem2 = XElement.Parse(doc.DocumentElement.InnerXml); //<-- XmlException

【讨论】:

  • 感谢使用XElement.Load( xmlElement.CreateNavigator().ReadSubtree() ); 的出色解决方案!如果您只需要转换为 XmlElement 的 XElement 实例,这是完美的。但是对于XmlComment 实例ReadSubtree() 抛出:System.InvalidOperationException: Operation is not valid due to the current position of the navigator
  • 对于使用这种方法的其他人,请确保您的所有XmlNodes 中的NodeTypeElement
【解决方案2】:

您可以尝试使用XmlElementInnerXml 属性来获取元素的xml 内容,然后使用XElement.Parse 将其解析为XElement

public static XElement ToXELement(this XmlElement source)
{
    return XElement.Parse(source.InnerXml);
}

【讨论】:

  • 为什么不使用 OuterXml 而不是 InnerXml?
【解决方案3】:

接管一切的唯一方法是使用 OuterXml。

XElement.Parse(xNode.OuterXml);

另一种方法是通过改变外部根元素。

XElement.Parse("<NewRoot>" + xNode.InnerXml + "</NewRoot>");

【讨论】:

    【解决方案4】:

    只要使用它:XElement e = XElement.Load(node.CreateReader());

    希望对你有帮助。

    例子:

    A real code example 上图代码

    public static XNode GetNodeByFilter(XNode node,ref SortedList filter, int position = 1) {

    XNode 结果 = null;

            if (filter.TryGetValue(position, out XMLSearchCriteria criteria))
            {
                while (node != null)
                {
                    XElement e = XElement.Load(node.CreateReader());
                    if (e.Name.LocalName.Equals(criteria.Node) && CheckIfAllAttributesMatch(e.Attributes(), criteria.Attributes))
                    {
                        if (++position <= filter.Count)
                        {
                            result = GetNodeByFilter(e.FirstNode, ref filter, position);
                            break;
                        }
                        else
                        {
                            result = node;
                        }
                    }
    
                    node = node.NextNode;
                }
            }
    
            return result;
        }
    

    【讨论】:

      【解决方案5】:

      实际上有一种非常直接的方法可以将 XNode 转换为 XElement:

      static XElement ToXElement( XNode node)
      {
          return node as XElement; // returns null if node is not an XElement
      }
      

      如果您 100% 确定节点是 XElement(或者如果不是,您准备处理异常,那么您可以简单地转换:(XElement)node

      【讨论】:

      • 问题是关于转换XmlNode,而不是XNode
      【解决方案6】:

      据我所知,您可以这样做:

      XElement xdoc = new XElement(node.Name, node.InnerXml);
      

      【讨论】:

      • 绝对不行,这会转义到整个xml,你会得到一个像&lt;root&gt; &amp;lt;sub&amp;gt;aaa&amp;lt;/sub&amp;gt; &lt;/root&gt;这样的单个节点
      • 对不起,但是,你怎么知道他的xml像“aaa”?也许他的节点比这更简单。
      • Marcos,不管简单与否,你的代码都行不通。它转义并将所有 innerXml 转换为字符串。您不简单地复制并粘贴我的 3 行代码并使用您的解决方案进行测试。无需讨论哪些可以轻松测试。
      • 你的 3 行?同样,也许他的 XML 更简单。
      • 马科斯,来吧,拜托......,这需要你几分钟。获取我的代码,附加您的解决方案,打开 VS 并使用您想要的 any xml 测试它们。 不,你的解决方案不起作用
      猜你喜欢
      • 2011-07-20
      • 1970-01-01
      • 2010-09-18
      • 1970-01-01
      • 1970-01-01
      • 2014-08-27
      • 1970-01-01
      • 1970-01-01
      • 2021-05-07
      相关资源
      最近更新 更多