C# SelectSingleNode 返回 null

Posted

技术标签:

【中文标题】C# SelectSingleNode 返回 null【英文标题】:C# SelectSingleNode returns null 【发布时间】:2021-10-24 15:13:55 【问题描述】:

我正在尝试从 .svg 文件中获取一个节点,该文件包含一些 xml 格式的信息。 这是我的代码:

                XmlDocument document = new XmlDocument();
                document.Load(openFileDialog.FileName);
                XmlNamespaceManager xmlnsManager = new XmlNamespaceManager(document.NameTable);
                xmlnsManager.AddNamespace("inkscape", "http://www.inkscape.org/namespaces/inkscape");
                xmlnsManager.AddNamespace("sodipodi", "http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd");
                xmlnsManager.AddNamespace("xlink", "http://www.w3.org/1999/xlink");
                xmlnsManager.AddNamespace("svg", "http://www.w3.org/2000/svg");

                XmlNode node = document.DocumentElement.SelectSingleNode("sodipodi:namedview/g/image]", xmlnsManager);

根据微软的文档,我也试过了:

descendant::sodipodi:namedview[sodipodi:g/sodipodi:image]

我还尝试了在 g/ 和 image 之前使用和不使用“sodipodo”的两个版本。 如果我只写“sodipodi:namedview”,它会找到节点并返回它,但我更愿意直接找到我需要的那个,而不是遍历它。 这是 xml 文件的简短版本:

<svg
   
   
   viewBox="0 0 210 297"
   version="1.1"
   id="svg5"
   inkscape:version="1.1 (c68e22c387, 2021-05-23)"
   sodipodi:docname="Zeichnung.svg"
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   xmlns:xlink="http://www.w3.org/1999/xlink"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:svg="http://www.w3.org/2000/svg">
  <sodipodi:namedview
     id="namedview7"
     pagecolor="#505050"
     bordercolor="#eeeeee"
     borderopacity="1"
     inkscape:pageshadow="0"
     inkscape:pageopacity="0"
     inkscape:pagecheckerboard="0"
     inkscape:document-units="mm"
     showgrid="false"
     inkscape:zoom="0.46324355"
     inkscape:cx="616.30648"
     inkscape:cy="601.19564"
     inkscape:window-
     inkscape:window-
     inkscape:window-x="1912"
     inkscape:window-y="101"
     inkscape:window-maximized="1"
     inkscape:current-layer="layer1" />
  <defs
     id="defs2">
    <rect
       x="69.078134"
       y="554.78377"
       
       
       id="rect1536" />
  </defs>
  <g
     inkscape:label="Ebene 1"
     inkscape:groupmode="layer"
     id="layer1">
    <image
       
       
       preserveAspectRatio="none"
       style="image-rendering:optimizeSpeed"
       xlink:href="Really long base64 string"
       id="image47"
       x="-2.8600111"
       y="-0.1732364" />
  </g>
</svg>

【问题讨论】:

据我所知,该图像不包含在 namedview 元素中,即没有子元素的元素。在 Visual Studio 中,输入您的简短 xml 版本,然后将 XPath 复制到图像,我得到/svg:svg/svg:g/svg:image。我错过了什么吗? @cph 不,你是对的,这解决了它,我只是瞎了,不知何故长达数小时 【参考方案1】:
    您的 XML 路径错误:g 不是 sodipodi:namedview 的子级。他们是兄弟姐妹。 XPath 格式错误:删除结尾的 ']' 字符 您已通过在svg 元素上声明xmlns="http://www.w3.org/2000/svg"(无别名/前缀)定义了默认命名空间,但您没有使用默认命名空间限定声明节点的子类型。根据 XML 命名空间规则,默认命名空间“继承”到定义命名空间的父元素的所有子元素(在这种情况下为 svg)。元素的默认命名空间定义了一个隐式前缀,隐式应用于所有子元素。

为了能够使用默认命名空间限定您的元素,您首先必须注册它

xmlnsManager.AddNamespace("default", "http://www.w3.org/2000/svg");

其中default 是映射默认命名空间的随机别名。

注册默认命名空间后,修改 XPath 以使用别名限定 svg 的子类型。

固定的 XPath 如下所示:

XmlNode node = document.DocumentElement.SelectSingleNode("default:g/default:image", xmlnsManager);

或者从svg 元素中删除默认命名空间声明xmlns="http://www.w3.org/2000/svg"

【讨论】:

【参考方案2】:

试试 xmllinq:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication2

    class Program
    
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        
            XDocument doc = XDocument.Load(FILENAME);
            XNamespace ns = doc.Root.GetDefaultNamespace();
            XNamespace nsXlink = doc.Root.GetNamespaceOfPrefix("xlink");
            XElement image = doc.Descendants(ns + "image").FirstOrDefault();
            double width = (double)image.Attribute("width");
            double height = (double)image.Attribute("height");
            string ratio = (string)image.Attribute("preserveAspectRatio");
            string style = (string)image.Attribute("style");
            string href = (string)image.Attribute(nsXlink + "href");
            string id = (string)image.Attribute("id");
            double x = (double)image.Attribute("x");
            double y = (double)image.Attribute("y");

        
    

【讨论】:

以上是关于C# SelectSingleNode 返回 null的主要内容,如果未能解决你的问题,请参考以下文章

C# Html 敏捷包 ( SelectSingleNode )

C# 中 XmlNode.SelectSingleNode(string xpath) 的正确用法是啥?

获取 xml 节点值尝试使用 SelectSingleNode 和 SelectNodes 使用 c#

SelectSingleNode 在 foreach 上返回错误的结果

当标签包含 xmlNamespace 时 SelectSingleNode 返回 null

Xml SelectSingleNode() 返回 null