Навигация и проверка SVG – Aspose.SVG для .NET
Иногда вам необходимо проверить содержимое файлов SVG, например, получить информацию о файле, элементах и иерархии. Aspose.SVG для .NET API полностью совместим с официальными спецификациями SVG и может использоваться для работы с объектной моделью документов SVG (DOM). API поддерживает широкий спектр функций навигации и проверки содержимого SVG.
В этом разделе вы узнаете:
- как просмотреть содержимое SVG в виде строки;
- как выполнить детальную проверку документа и его элементов с помощью API;
- какие есть способы получения информации о том или ином элементе из SVG-файла;
- об использовании пользовательских фильтров для перебора элементов документа;
- как перемещаться по документу с помощью CSS Selector или XPath Query.
Вы можете загрузить полные примеры и файлы данных с GitHub. О загрузке с GitHub и запуске примеров вы узнаете из раздела Как запускать примеры.
Просмотр содержимого SVG
Самый простой способ проверить содержимое документа – просмотреть содержимое как строку. Свойства InnerHTML и OuterHTML класса
Element возвращают фрагмент XML (или HTML), который представляет элемент и его содержимое. Они разработаны именно для просмотра содержимого SVG в виде строки.
В следующем примере кода показано, как просмотреть содержимое файла
bezier-curves.svg в консоли.
1using Aspose.Svg;
2using System.IO; 1// Get SVG document OuterHTML in C#
2
3// Load an SVG document
4using (SVGDocument document = new SVGDocument(Path.Combine(DataDir, "bezier-curves.svg")))
5{
6 // Use the OuterHTML property
7 string html = document.DocumentElement.OuterHTML;
8
9 Console.WriteLine(html);
10}
11// View the document contentНавигация и проверка SVG с использованием DOM
Извлечение информации о конкретном элементе SVG
В следующем примере показано, как извлечь информацию о конкретном элементе SVG из файла shapes.svg:
1using Aspose.Svg;
2using System.IO;
3using System.Linq; 1// Extract information about specific SVG element
2
3string documentPath = Path.Combine(DataDir, "shapes_svg.svg");
4
5// Load a document from a file
6using (SVGDocument document = new SVGDocument(documentPath))
7{
8 // Get the root <svg> element of the document
9 Element svg = document.DocumentElement;
10
11 // Find the first child element with a given tag name
12 SVGGElement g = svg.GetElementsByTagName("g").First() as SVGGElement;
13 SVGRectElement rect = g.FirstElementChild as SVGRectElement;
14
15 Console.WriteLine("Height: {0}", rect.Height);// 100
16 Console.WriteLine("Width: {0}", rect.Width); // 100
17}В этом примере использование свойства
DocumentElement обеспечивает прямой доступ к элементу <svg> документа. Метод
GetElementsByTagName() класса
Element возвращает NodeList всех элементов-потомков с заданным именем тега; в этом случае возвращаемым элементом является первый элемент <g>. Свойство
FirstElementChild возвращает первый узел дочернего элемента этого элемента. В этом примере первым дочерним элементом элемента <g> является элемент <rect>, для которого печатаются значения ширины и высоты.
Проверка документа SVG и его элементов
Aspose.SVG содержит список методов, основанных на Спецификациях обхода элементов. Выполнить детальную проверку документа и его элементов можно с помощью API ( shapes.svg). В следующем примере кода показано обобщенное использование функций обхода элементов.
1using Aspose.Svg;
2using System.IO; 1// Traverse SVG elements in C# programmatically
2
3// Load an SVG document
4using (SVGDocument document = new SVGDocument(Path.Combine(DataDir, "shapes_svg.svg")))
5{
6 // Get direct access to the <svg> element of the document
7 Element element = document.DocumentElement;
8 Console.WriteLine(element.TagName); // svg
9
10 // Use the LastElementChild property
11 element = element.LastElementChild;
12 Console.WriteLine(element.TagName); // g
13
14 // Use the FirstElementChild property
15 element = element.FirstElementChild;
16 Console.WriteLine(element.TagName); // rect
17}Элемент <svg> является контейнером и используется как самый внешний элемент документов SVG. Чтобы указать элемент <svg>, вы можете применить несколько способов:
- Свойство
DocumentElementкласса Document предоставляет прямой доступ к элементу<svg>документа. В приведенном выше фрагменте кода мы используем этот способ. - Свойство
RootElementкласса SVGDocument возвращает корневой элемент<svg>в иерархии документа. Чтобы указать элемент<svg>, вы можете применить следующий код:
1var svgElement = document.RootElement;Свойство LastElementChild класса Document возвращает последний дочерний элемент элемента <svg>. Это элемент <g>. Согласно приведенному выше фрагменту кода, элемент переменной снова перегружается, а свойство FirstElementChild возвращает первого дочернего элемента элемента <g>. Это элемент <rect>.
Использование пользовательского фильтра
API Aspose.SVG позволяет вам определять собственные фильтры и использовать их для перебора элементов документа, как показано в следующем примере кода:
1using Aspose.Svg;
2using System.IO;
3using Aspose.Svg.Dom;
4using Aspose.Svg.Dom.Traversal.Filters; 1// Iterate SVG nodes with NodeIterator in C#
2
3using (SVGDocument document = new SVGDocument(Path.Combine(DataDir, "shapes.svg")))
4{
5 // Create a node iterator
6 using (INodeIterator iterator = document.CreateNodeIterator(document, NodeFilter.SHOW_ALL, new RectFilter()))
7 {
8 Node node;
9 while ((node = iterator.NextNode()) != null)
10 {
11 }
12 }
13}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 }Метод
CreateNodeIterator(Node, Int64, INodeFilter) интерфейса
IDocumentTraversal создает новый итератор с корнем в указанном Node (в нашем примере это document). В качестве параметров метод принимает флаг Node, Int64, определяющий типы узлов для итератора, и INodeFilter (в нашем примере это RectFilter()).
Класс RectFilter наследует от класса
NodeFilter метод
AcceptNode(Node n). Метод принимает узел и проверяет, проходит ли он фильтр или нет; метод возвращает короткое сообщение, указывающее, найден ли узел или нет.
В итераторе мы используем метод
NextNode() интерфейса
INodeIterator для доступа ко всем узлам документа. Первый вызов NextNode() возвращает первый узел и перемещает позицию итератора в наборе. Свойство OuterHTML класса
Element возвращает содержимое элемента, которое будет напечатано.
Вы можете загрузить полные примеры и файлы данных с GitHub. О загрузке с GitHub и запуске примеров вы узнаете из раздела Как запускать примеры.
Редактировать SVG с помощью селектора CSS
Aspose.SVG для .NET также реализует спецификацию CSS Selector, которая позволяет вам перемещаться по документу.
Метод
QuerySelector(selector) класса
Element позволяет получить первый элемент в документе, соответствующий указанному селектору. Метод
QuerySelectorAll(selector) принимает в качестве параметра селектор запроса и возвращает NodeList всех элементов, соответствующих селектору. С получившимися элементами можно производить различные манипуляции: менять его текст, атрибуты, стили CSS и так далее.
В следующих примерах мы используем методы QuerySelector() и QuerySelectorAll() для навигации по документу SVG и поиска необходимых элементов.
Пример 1
В примере 1 мы редактируем исходный файл owl.svg – это SVG-изображение совы, нарисованное элементами пути и круга.
- находим в SVG документе все элементы круга и меняем их свойства – делаем сове большие голубые глаза;
- находим элемент пути для крыла совы и украшаем его.
Использование селектора CSS:
1using Aspose.Svg;
2using System.IO;
3using Aspose.Svg.Dom;
4using Aspose.Svg.Collections; 1// Edit SVG elements with CSS selectors in C#
2
3// Load an SVG document
4using (SVGDocument document = new SVGDocument(new Url("https://docs.aspose.com/svg/files/owl.svg")))
5{
6 // Get the root <svg> element of the document
7 SVGSVGElement svgElement = document.RootElement;
8
9 // Find the first element that matches the specified in selector
10 SVGGElement gElement = svgElement.QuerySelector("g") as SVGGElement;
11
12 // Find all <circle> elements in a <g> element
13 NodeList circleNodes = gElement.QuerySelectorAll("circle");
14
15 // Make big blue eyes
16 foreach (Node circleNode in circleNodes)
17 {
18 SVGCircleElement circleElement = circleNode as SVGCircleElement;
19 circleElement.R.BaseVal.Value *= 1.5F;
20 circleElement.SetAttribute("stroke", "blue");
21 }
22
23 // Get a path for the owl's wing
24 SVGPathElement wingPath = gElement.QuerySelector("path:nth-child(2)") as SVGPathElement;
25
26 // Apply style attributes to the wing
27 wingPath.SetAttribute("stroke-width", "16");
28 wingPath.SetAttribute("stroke-dasharray", "2 8");
29
30 document.Save(Path.Combine(OutputDir, "owl-edited1.svg"));
31}Посмотреть и сохранить отредактированный SVG-файл можно по ссылке – owl-edited1.svg.
Пример 2
В этом примере мы покажем, как использовать селектор CSS для навигации по документу в целях редактирования. Продолжаем редактировать исходный файл owl.svg:
- в первой части Примера 2 круглые глаза совы будут заменены на квадратные и перекрашены.
Мы создаем новый элемент <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; 1// Replace SVG circles with rectangles in C#
2
3// Load an SVG document
4using (SVGDocument document = new SVGDocument(new Url("https://docs.aspose.com/svg/files/owl.svg")))
5{
6 // Get the root <svg> element of the document
7 SVGSVGElement svgElement = document.RootElement;
8
9 // Create a new <g> element with style attributes and append it as the last child of the <svg> element
10 SVGGElement gElement = (SVGGElement)document.CreateElementNS(SvgNamespace, "g");
11 gElement.SetAttribute("fill", "none");
12 gElement.SetAttribute("stroke-width", "2");
13 svgElement.AppendChild(gElement);
14
15 // Find all <circle> elements from the first <g> element
16 NodeList circleNodes = svgElement.QuerySelectorAll("g:first-child > circle");
17
18 // Make square sky-blue eyes
19 foreach (Node circleNode in circleNodes)
20 {
21 SVGCircleElement circleElement = circleNode as SVGCircleElement;
22
23 float cx = circleElement.Cx.BaseVal.Value;
24 float cy = circleElement.Cy.BaseVal.Value;
25 float r = circleElement.R.BaseVal.Value;
26
27 SVGRectElement rectElement = (SVGRectElement)document.CreateElementNS(SvgNamespace, "rect");
28 rectElement.X.BaseVal.Value = cx - r;
29 rectElement.Y.BaseVal.Value = cy - r;
30 rectElement.Width.BaseVal.Value = 3 * r;
31 rectElement.Height.BaseVal.Value = 3 * r;
32 rectElement.SetAttribute("stroke", "SkyBlue");
33
34 // Add a <rectangle> element into the second (new) <g> element and remove <circle> elements
35 gElement.AppendChild(rectElement);
36 circleElement.Remove();
37 }
38 // Recolor last rectangle in the second (new) <g> element
39 Element lastRect = gElement.LastElementChild;
40 lastRect.SetAttribute("stroke", "red");
41
42 document.Save(Path.Combine(OutputDir, "owl-svg-eyes.svg"));
43}- во второй части примера 2 траектория крыла совы будет изменена с кривой (path) на ломаную и перекрашена.
1using Aspose.Svg;
2using System.IO;
3using Aspose.Svg.Dom;
4using Aspose.Svg.Collections; 1// Modify and rewrite SVG path data in C#
2
3// Load an SVG document
4using (SVGDocument document = new SVGDocument(Path.Combine(DataDir, "owl-svg-eyes.svg")))
5{
6 SVGSVGElement svgElement = document.RootElement;
7
8 // Get a path for owl's body from the first <g> element
9 Element bodyPath = (svgElement.QuerySelector("g:first-child") as SVGGElement).FirstElementChild;
10 bodyPath.SetAttribute("stroke", "Teal");
11
12 // Get a path for the owl's wing from the first <g> element
13 SVGPathElement wingPath = svgElement.QuerySelector("g:first-child > path:nth-child(2)") as SVGPathElement;
14
15 // Form new wing path data based on the old
16 string d = "";
17 foreach (SVGPathSeg pathSeg in wingPath.PathSegList)
18 {
19 if (pathSeg is SVGPathSegMovetoAbs)
20 {
21 SVGPathSegMovetoAbs pathSegMovetoAbs = pathSeg as SVGPathSegMovetoAbs;
22
23 d += string.Format(" M {0} {1}", pathSegMovetoAbs.X, pathSegMovetoAbs.Y);
24 }
25 if (pathSeg is SVGPathSegCurvetoCubicAbs)
26 {
27 SVGPathSegCurvetoCubicAbs pathSegCurvetoCubicAbs = pathSeg as SVGPathSegCurvetoCubicAbs;
28
29 d += string.Format(
30 " L {0} {1} L {2} {3}",
31 (pathSegCurvetoCubicAbs.X1 + pathSegCurvetoCubicAbs.X2) / 2F,
32 (pathSegCurvetoCubicAbs.Y1 + pathSegCurvetoCubicAbs.Y2) / 2F,
33 pathSegCurvetoCubicAbs.X,
34 pathSegCurvetoCubicAbs.Y
35 );
36 }
37 }
38 // Set d attribute - new path data formation
39 wingPath.SetAttribute("d", d.Trim());
40 wingPath.SetAttribute("stroke", "Teal");
41
42 document.Save(Path.Combine(OutputDir, "owl-edited2.svg"));
43}На рисунке: исходная картинка (а), отредактированная картинка по примеру 1 (b), отредактированная картинка по примеру 2 (c).

В приведенных выше примерах мы берем исходный файл owl.svg и редактируем некоторые элементы. Глаза и крылья совы мы попытались украсить различными способами, используя функции навигации и проверки API Aspose.SVG. Посмотреть и сохранить отредактированный SVG-файл можно по ссылке – owl-edited2.svg.
Навигация по SVG с помощью запроса XPath
XPath Query ( XML Path Language), часто называемый просто XPath, представляет собой язык запросов, используемый для запроса данных из документов. Он основан на DOM-представлении документа SVG и выбирает узлы по различным критериям. Синтаксис выражений XPath довольно прост и, что более важно, его легко читать и поддерживать.
Aspose.SVG также имеет мощную реализацию спецификаций XPath наряду со спецификациями обхода. Это позволит вам использовать XPath Query для навигации по документу ( 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 и запуске примеров вы узнаете из раздела Как запускать примеры.