导航 SVG – Navigation & Inspection SVG – Aspose.SVG for .NET

有时您需要检查 SVG 文件的内容,例如,获取有关文件、元素和层次结构的信息。 Aspose.SVG for .NET API 与官方 SVG 规范 完全兼容,可用于遍历 SVG 文档对象模型 (DOM)。该 API 支持 SVG 内容的各种导航和检查功能。

在本节中,您将了解:

您可以从 GitHub 下载完整的示例和数据文件。关于从 GitHub 下载并运行示例,您可以从 如何运行示例 部分找到。

查看 SVG 内容

检查文档内容的最简单方法是将内容视为字符串。 Element 类的属性 InnerHTMLOuterHTML 返回表示元素及其内容的 XML(或 HTML)片段。它们是专门为将 SVG 内容作为字符串查看而开发的。 以下代码示例演示如何在控制台中查看 bezier-curves.svg 文件的内容。

 1using Aspose.Svg;
 2using System.IO;
 3...
 4
 5    string documentPath = Path.Combine(DataDir, "bezier-curves.svg");
 6
 7	// Load an SVG document
 8	using (var document = new SVGDocument(documentPath))
 9	{
10	     var html = document.DocumentElement.OuterHTML;
11
12	     Console.WriteLine(html);
13	}	
14	// View the document content
15	

使用 DOM 导航和检查 SVG

提取有关特定 SVG 元素的信息

以下示例演示如何从文件 shapes.svg 中提取有关特定 SVG 元素的信息:

 1using Aspose.Svg;
 2using System.IO;
 3using System.Linq;
 4...
 5
 6    //Load a document from a file
 7    string documentPath = Path.Combine(DataDir, "shapes.svg");
 8
 9    using (var document = new SVGDocument(documentPath))
10    {
11        // Get the root svg element of the document
12    	var svg = document.DocumentElement;
13
14    	// Find the first child element with a given tag name
15        var g = svg.GetElementsByTagName("g").First() as SVGGElement;
16
17        var rect = g.FirstElementChild as SVGRectElement;
18
19        Console.WriteLine("Height: {0}", rect.Height);// 90
20        Console.WriteLine("Width: {0}", rect.Width); // 100
21    }

在示例中, DocumentElement 属性的使用允许直接访问文档的 <svg> 元素。 Element 类的方法 GetElementsByTagName() 返回具有给定标签名称的所有后代元素的 NodeList;在这种情况下,返回元素是第一个 <g> 元素。 FirstElementChild 属性返回该元素的第一个子元素节点。在示例中, <g> 元素中的第一个子元素是 <rect> 元素,将打印该元素的宽度和高度值。

检查 SVG 文档及其元素

Aspose.SVG 包含基于 元素遍历规范 的方法列表。您可以使用 API ( shapes.svg) 对文档及其元素执行详细检查。以下代码示例显示了元素遍历功能的一般用法。

 1using Aspose.Svg;
 2using System.IO;
 3...
 4
 5    // Load a document
 6	string documentPath = Path.Combine(DataDir, "shapes.svg");
 7
 8    using (var document = new SVGDocument(documentPath))
 9    {
10        var element = document.DocumentElement;
11        Console.WriteLine(element.TagName); // svg
12        
13        element = element.LastElementChild;
14        Console.WriteLine(element.TagName); // g
15
16        element = element.FirstElementChild;
17        Console.WriteLine(element.TagName); // rect
18    }

<svg> 元素是一个容器,它用作 SVG 文档的最外层元素。要指向 <svg> 元素,您可以应用几种方法:

1var svgElement = document.RootElement;

Document 类的 LastElementChild 属性返回<svg>元素的最后一个子元素。它是 <g> 元素。根据上面的代码片段,变量元素再次被重载,FirstElementChild 属性返回 <g> 元素的第一个子元素。它是 <rect> 元素。

自定义过滤器的使用

Aspose.SVG API 允许您定义自定义过滤器并使用它们来迭代文档元素,如以下代码示例所示:

 1using Aspose.Svg;
 2using System.IO;
 3using Aspose.Svg.Dom;
 4using Aspose.Svg.Dom.Traversal.Filters;
 5...
 6
 7    using (var document = new SVGDocument(Path.Combine(DataDir, "shapes.svg")))
 8    {
 9        // Create a node iterator
10        using (var iterator = document.CreateNodeIterator(document, NodeFilter.SHOW_ALL, new RectFilter()))
11        {
12            Node node;
13            while ((node = iterator.NextNode()) != null)
14            {
15                Console.WriteLine((node as Element)?.OuterHTML);
16            }
17        }
18    }

where the RectFilter class is defined as follows:

1    public class RectFilter : NodeFilter
2    {
3        public override short AcceptNode(Node n)
4        {
5            return string.Equals("rect", n.NodeName) ? FILTER_ACCEPT : FILTER_REJECT;
6        }
7    }

IDocumentTraversal 接口的 CreateNodeIterator(Node, Int64, INodeFilter) 方法创建一个以指定 Node 为根的新迭代器(在我们的示例中,它是 document)。该方法采用 Node 、指定迭代器节点类型的 Int64 标志以及要使用的 INodeFilter 作为参数(在我们的示例中,它是 RectFilter())。

RectFilter 类继承自 NodeFilter 类的 AcceptNode(Node n) 方法。该方法采用一个 Node 并测试它是否通过过滤器;该方法返回一个短值,指示是否找到该节点。

在迭代器中,我们使用 INodeIterator 接口的 NextNode() 方法来访问文档的所有节点。第一次调用 NextNode() 返回第一个节点并移动迭代器在集合中的位置。 Element 类的 OuterHTML 属性返回将要打印的元素的内容。

您可以从 GitHub 下载完整的示例和数据文件。关于从 GitHub 下载并运行示例,您可以从 如何运行示例 部分找到。

使用 CSS 选择器编辑 SVG

Aspose.SVG for .NET 还实现了 CSS 选择器规范,允许您使用类似 CSS 的样式来浏览文档。

Element 类的 QuerySelector(selector) 方法允许您获取文档中与指定选择器匹配的第一个元素。 QuerySelectorAll(selector) 方法将查询选择器作为参数,并返回与选择器匹配的所有元素的 NodeList。使用生成的元素,您可以进行各种操作:更改其文本、属性、CSS 样式等。

在以下示例中,我们使用 QuerySelector() 和 QuerySelectorAll() 方法在 SVG 文档中导航并搜索所需的元素。

实施例1

在示例 1 中,我们编辑源 owl.svg 文件 – 是由路径和圆形元素绘制的猫头鹰 SVG 图片。

使用 CSS 选择器:

 1using Aspose.Svg;
 2using System.IO;
 3using Aspose.Svg.Dom;
 4using Aspose.Svg.Collections;
 5...
 6
 7    using (var document = new SVGDocument(new Url("https://docs.aspose.com/svg/files/owl.svg")))
 8    {
 9        // Get root svg element of the document
10        var svgElement = document.RootElement;
11
12        // Find the first element that matches the specified in selector – g element
13        SVGGElement gElement = svgElement.QuerySelector("g") as SVGGElement;
14
15        // Find all circle elements in g element
16        NodeList circleNodes = gElement.QuerySelectorAll("circle");
17
18        // Make big blue eyes
19        foreach (Node circleNode in circleNodes)
20        {
21            SVGCircleElement circleElement = circleNode as SVGCircleElement;
22
23            circleElement.R.BaseVal.Value *= 1.5F;
24            circleElement.SetAttribute("stroke", "blue");
25        }
26
27        // Get path for an owl wing
28        SVGPathElement wingPath = gElement.QuerySelector("path:nth-child(2)") as SVGPathElement;
29    
30        // Apply style attributes to the wing
31        wingPath.SetAttribute("stroke-width", "16");
32        wingPath.SetAttribute("stroke-dasharray", "2 8");
33
34        document.Save(OutputDir + "owl-edited1.svg");
35    }

您可以通过链接 – owl-edited1.svg 查看并保存编辑后的 ​​SVG 文件。

实施例2

在此示例中,我们展示了如何使用 CSS 选择器来导航文档以进行编辑。我们继续编辑源 owl.svg 文件:

我们创建一个新的 <g> 元素,向其中添加子元素的公共属性(它们将是新的方眼)并将其附加为 <svg> 元素中的最后一个子元素(请参阅 编辑SVG文件);使用 QuerySelectorAll(“g:first-child > circle”) 方法我们找到第一个 <g> 元素中的所有圆;然后我们创建具有大小属性​​的 <rect> 元素,将矩形添加到第二个 <g> 元素中并删除圆形元素。

下面的代码片段演示了如何实现这个任务:

 1using Aspose.Svg;
 2using System.IO;
 3using Aspose.Svg.Dom;
 4using Aspose.Svg.Collections;
 5...
 6
 7    // Create a new g element with style attributes and append it as the last child in svg element
 8    var gElement = (SVGGElement)document.CreateElementNS(SvgNamespace, "g");
 9    gElement.SetAttribute("fill", "none");
10    gElement.SetAttribute("stroke-width", "2");
11    svgElement.AppendChild(gElement);
12
13    // Find all circle elements from the first g element
14    NodeList circleNodes = svgElement.QuerySelectorAll("g:first-child > circle");
15
16    // Make square sky-blue eyes
17    foreach (Node circleNode in circleNodes)
18    {
19        var circleElement = circleNode as SVGCircleElement;
20
21        float cx = circleElement.Cx.BaseVal.Value;
22        float cy = circleElement.Cy.BaseVal.Value;
23        float r = circleElement.R.BaseVal.Value;
24
25        var rectElement = (SVGRectElement)document.CreateElementNS(SvgNamespace, "rect");
26        rectElement.X.BaseVal.Value = cx - r;
27        rectElement.Y.BaseVal.Value = cy - r;
28        rectElement.Width.BaseVal.Value = 3 * r;
29        rectElement.Height.BaseVal.Value = 3 * r;
30        rectElement.SetAttribute("stroke", "SkyBlue");
31
32        // Add the rectangle element into the last (new) g element 
33        gElement.AppendChild(rectElement);
34
35    	// Remove the circle elements
36        circleElement.Remove();
37    }
38    // Recolor last rectangle in the last (new) g element
39    Element lastRect = gElement.LastElementChild;
40    lastRect.SetAttribute("stroke", "red");
 1using Aspose.Svg;
 2using System.IO;
 3using Aspose.Svg.Dom;
 4using Aspose.Svg.Collections;
 5...
 6
 7    // Get path for owl body from the first g element
 8    Element bodyPath = (svgElement.QuerySelector("g:first-child") as SVGGElement).FirstElementChild;
 9    bodyPath.SetAttribute("stroke", "Teal");
10
11    // Get path for owl wing from the first g element
12    SVGPathElement wingPath = svgElement.QuerySelector("g:first-child > path:nth-child(2)") as SVGPathElement;
13
14    // Form new wing path data based on the old
15    string d = "";
16    foreach (SVGPathSeg pathSeg in wingPath.PathSegList)
17    {
18        if (pathSeg is SVGPathSegMovetoAbs)
19        {
20            SVGPathSegMovetoAbs pathSegMovetoAbs = pathSeg as SVGPathSegMovetoAbs;
21
22            d += string.Format(" M {0} {1}", pathSegMovetoAbs.X, pathSegMovetoAbs.Y);
23        }
24        if (pathSeg is SVGPathSegCurvetoCubicAbs)
25        {
26            SVGPathSegCurvetoCubicAbs pathSegCurvetoCubicAbs = pathSeg as SVGPathSegCurvetoCubicAbs;
27            
28            d += string.Format(
29                " L {0} {1} L {2} {3}",
30                (pathSegCurvetoCubicAbs.X1 + pathSegCurvetoCubicAbs.X2) / 2F,
31                (pathSegCurvetoCubicAbs.Y1 + pathSegCurvetoCubicAbs.Y2) / 2F,
32                pathSegCurvetoCubicAbs.X,
33                pathSegCurvetoCubicAbs.Y
34            );
35        }
36    }
37    // Set d attribute – new path data formation
38    wingPath.SetAttribute("d", d.Trim());
39    wingPath.SetAttribute("stroke", "Teal");
40
41    document.Save(OutputDir + "owl-edited2.svg");

上图:源图片(a)、根据示例1编辑后的图片(b)、根据示例2编辑后的图片(c)。

文本“原始和两张编辑过的猫头鹰图像”

在上面的示例中,我们采用源 owl.svg 文件并编辑一些元素。我们尝试使用导航和检查 Aspose.SVG API 函数以各种方式装饰猫头鹰的眼睛和翅膀。您可以通过链接 – owl-edited2.svg 查看并保存编辑后的 ​​SVG 文件。

使用 XPath 查询导航 SVG

XPath 查询( XML 路径语言),通常简称为 XPath,是一种用于从文档查询数据的查询语言。它基于 SVG 文档的 DOM 表示,并根据各种标准选择节点。 XPath 表达式的语法非常简单,更重要的是,它易于阅读和支持。

Aspose.SVG 还具有强大的 XPath 规范实现以及遍历规范。这使您能够使用 XPath 查询来浏览文档 ( shapes.svg),如以下代码示例所示:

 1using Aspose.Svg;
 2using System.IO;
 3using Aspose.Svg.Dom;
 4using Aspose.Svg.Collections;
 5...
 6
 7    using (var document = new SVGDocument(Path.Combine(DataDir, "shapes.svg")))
 8    {
 9        //  Evaluate XPath expression
10        var xpathResult = document.Evaluate("//rect[@x='120']", document, null, (Dom.XPath.XPathResultType)XPathResultType.Any, null);
11
12        //  Get the next evaluated node
13        Console.WriteLine((xpathResult.IterateNext() as Element)?.OuterHTML); 
14    }

您可以从 GitHub 下载完整的示例和数据文件。

关于从 GitHub 下载并运行示例,您可以从 如何运行示例 部分找到。

Subscribe to Aspose Product Updates

Get monthly newsletters & offers directly delivered to your mailbox.