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 上返回错误的结果