Навигация и проверка 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;
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
Навигация и проверка SVG с использованием DOM
Извлечение информации о конкретном элементе SVG
В следующем примере показано, как извлечь информацию о конкретном элементе SVG из файла shapes.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>
документа. Метод
GetElementsByTagName() класса
Element возвращает 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>
, вы можете применить несколько способов:
- Свойство
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;
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 }
где класс RectFilter определяется следующим образом:
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;
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 }
Посмотреть и сохранить отредактированный 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;
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");
- во второй части примера 2 траектория крыла совы будет изменена с кривой (path) на ломаную и перекрашена.
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");
На рисунке: исходная картинка (а), отредактированная картинка по примеру 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 и запуске примеров вы узнаете из раздела Как запускать примеры.