如何从xml-svg文件中获取更多值?

时间:2017-06-02 22:05:15

标签: c# xml

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Xml;
using System.Xml.Linq;
using System.IO;
using System.Linq;

public class XmlReader : MonoBehaviour
{
    public enum Rects
    {
        WIDTH, HEIGHT, X, Y, COLOR, ANGLE
    }

    void Start ()
    {
        ParseXml();
    }

    private void ParseXml()
    {
        XDocument document = XDocument.Load(@"C:\Users\mysvg\Documents\my.svg");
        XNamespace ns = "http://www.w3.org/2000/svg";

        var list = document.Root.Descendants(ns + "rect").Select(e => new {
            Style = e.Attribute("fill").Value,
            Angle = e.Attribute("transform").Value,
            Width = e.Attribute("width").Value,
            Height = e.Attribute("height").Value,
            X = e.Attribute("x").Value
        });

        foreach (var item in list)
        {
            string result = string.Format("Width: {0}, Height: {1}, X: {2}", item.Width, item.Height, item.X);
        }
    }

    // Update is called once per frame
    void Update ()
    {

    }
}

svg文件格式为:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->

<svg
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:cc="http://creativecommons.org/ns#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   width="210mm"
   height="297mm"
   viewBox="0 0 744.09448819 1052.3622047"
   id="svg2"
   version="1.1"
   inkscape:version="0.91 r13725"
   sodipodi:docname="drawing.svg"
   inkscape:export-filename="C:\Users\adili_000\Desktop\drawing.png"
   inkscape:export-xdpi="125"
   inkscape:export-ydpi="125">
  <defs
     id="defs4" />
  <sodipodi:namedview
     id="base"
     pagecolor="#ffffff"
     bordercolor="#666666"
     borderopacity="1.0"
     inkscape:pageopacity="0.0"
     inkscape:pageshadow="2"
     inkscape:zoom="1.4"
     inkscape:cx="470.51389"
     inkscape:cy="692.09768"
     inkscape:document-units="px"
     inkscape:current-layer="layer1"
     showgrid="false"
     inkscape:window-width="1920"
     inkscape:window-height="1017"
     inkscape:window-x="-8"
     inkscape:window-y="-8"
     inkscape:window-maximized="1">
    <inkscape:grid
       type="xygrid"
       id="grid4172" />
  </sodipodi:namedview>
  <metadata
     id="metadata7">
    <rdf:RDF>
      <cc:Work
         rdf:about="">
        <dc:format>image/svg+xml</dc:format>
        <dc:type
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
      </cc:Work>
    </rdf:RDF>
  </metadata>
  <g
     inkscape:label="Layer 1"
     inkscape:groupmode="layer"
     id="layer1">
    <rect
       style="opacity:1;fill:#00c8fc;fill-opacity:0.98823529;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
       id="rect4155"
       width="45.714287"
       height="30"
       x="37.387959"
       y="115.30345" />
    <rect
       style="opacity:1;fill:#00c8fc;fill-opacity:0.98823529;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
       id="rect4155-5"
       width="45.714287"
       height="30"
       x="91.899246"
       y="115.40621" />
    <rect
<path
       sodipodi:type="star"
       style="opacity:1;fill:#f1c8fc;fill-opacity:0.98823529;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
       id="path4841"
       sodipodi:sides="8"
       sodipodi:cx="288.21429"
       sodipodi:cy="396.29076"
       sodipodi:r1="21.58555"
       sodipodi:r2="10.792775"
       sodipodi:arg1="1.0471976"
       sodipodi:arg2="1.4398967"
       inkscape:flatsided="false"
       inkscape:rounded="0"
       inkscape:randomized="0"
       d="m 299.00707,414.98441 -9.38404,-7.9932 -6.99549,10.1496 -0.98347,-12.28755 -12.12341,2.23029 7.99319,-9.38404 -10.1496,-6.99549 12.28756,-0.98347 -2.23029,-12.12341 9.38404,7.99319 6.99549,-10.1496 0.98347,12.28756 12.12341,-2.23029 -7.99319,9.38403 10.14959,6.99549 -12.28755,0.98348 z" />
  </g>
</svg>

我无法弄清楚如何做的一些问题。

第一个问题是如何获得每个rect填充的填充值我的意思是颜色:style =&#34;不透明度:1;填充:#00c8fc;填充不透明度:0.98823529;填充 - 所以我需要获取/提取#00c8fc。

另一个值是变换的6个数字,其中一些变换在底部变换:我没有添加svg的全部内容,但是底部的一些内容是:

<rect
       style="opacity:1;fill:#00c8fc;fill-opacity:0.98823529;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
       id="rect4155-5-6-56-6-2"
       width="27.153143"
       height="13.716971"
       x="79.204071"
       y="477.30438"
       transform="matrix(0.9672488,-0.25383017,0.25383017,0.9672488,0,0)" />

我需要得到6个数字:0.9672488,-0.25383017,0.25383017,0.9672488,0,0

更新

为了获得样式部分,我添加了一行:

Style = e.Attribute("style").Value.Substring(16,6),

现在我如何将transform / matrix 6数字作为6个int变量? 然后我需要用6个数字进行一些计算。

问题是并非每个rect都在底部进行了转换: 我试着添加一行:

Transform= e.Attribute("transform").Value.Substring(18, 43),

但是获得null异常,因为不是每个rect都有变换。

如何提取已转换6个数字的矩形?例如:

变换=&#34;矩阵(0.98125852,-0.1926959,0.1926959,0.98125852,0,0)&#34;

所以我需要在6个数字中加入6个int变量:0.98125852,-0.1926959,0.1926959,0.98125852,0,0

2 个答案:

答案 0 :(得分:1)

我使用xml linq和正则表达式以及字典。工作得很好

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

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(FILENAME);

            Rect.rectangles = doc.Descendants().Where(x => x.Name.LocalName == "rect").Select(x => new Rect()
            {
                style = Rect.GetStyle((string)x.Attribute("style")),
                id = (string)x.Attribute("id"),
                width = (double)x.Attribute("width"),
                height = (double)x.Attribute("width"),
                x = (double?)x.Attribute("width"),
                y = (double?)x.Attribute("width"),
                transform = x.Attribute("transform") == null ? null : (object)Rect.GetTransform((string)x.Attribute("transform"))
            }).ToList();


        }
    }
    public class Rect
    {
        public static List<Rect> rectangles { get; set; }
        public Dictionary<string, string> style { get; set; }
        public string id { get; set; }
        public double width { get; set; }
        public double height { get; set; }
        public double? x { get; set; }
        public double? y { get; set; }
        public object transform { get; set; }

        public static Dictionary<string, string> GetStyle(string styles)
        {
            string pattern = @"(?'name'[^:]+):(?'value'.*)";
            string[] splitArray = styles.Split(new char[] { ';' });
            Dictionary<string, string> style = splitArray.Select(x => Regex.Match(x, pattern))
                .GroupBy(x => x.Groups["name"].Value, y => y.Groups["value"].Value)
                .ToDictionary(x => x.Key, y => y.FirstOrDefault());
            return style;
        }
        public static KeyValuePair<double, double> GetTransform(string matrix)
        {
            string pattern = @"[-+]?\d+\.\d+";
            MatchCollection matches = Regex.Matches(matrix, pattern);
            KeyValuePair<double, double> kp = new KeyValuePair<double, double>(
                double.Parse(matches[0].Value),
                double.Parse(matches[0].Value)
                );

            return kp;
        }
    }
}

答案 1 :(得分:0)

  

为了获得样式部分,我添加了一行:Style = e.Attribute(&#34; style&#34;)。Value.Substring(16,6),

这假设fill将从第16位开始,由于许多原因可能不正确(例如 style =&#34; opacity:0.987; fill = ...&#34; < / em>)并且该值将是6个字符长( style =&#34;不透明度:1;填充=红色; ...&#34; )不正确。这应该会更好:

Style = e.Attribute("style")?.Value.Split(';').Where(property => property.StartsWith("fill:")).Select(property => property.Substring(5)).FirstOrDefault(),


  

所以我需要在6个数字中加入6个int变量:0.98125852,-0.1926959,0.1926959,0.98125852,0,0

首先,由于这些数字是浮点数(不是整数),你当然需要浮点数或双变量。 其次,为了防止在不存在transform属性时出现异常,请使用?.运算符,当value为null时停止表达式求值:

Angle = ParseTransformMatrix(e.Attribute("transform")?.Value),

并使用此方法从属性字符串中提取6个转换矩阵参数:

static double[] ParseTransformMatrix(string transform)
{
    if (String.IsNullOrWhiteSpace(transform))
        return null;

    if (!(transform.StartsWith("matrix(") && transform.EndsWith(")")))
        return null;

    return transform
        .Substring(7, transform.Length - 8)
        .Split(',')
        .Select(s => Double.Parse(s, System.Globalization.CultureInfo.InvariantCulture))
        .ToArray();
}

有些人可能更喜欢使用Regex解析此类字符串。但我并不喜欢这样的人。

另请注意,我的答案仅适用于此特定svg文件,但可能不适用于其他文件,因为解析svg文件可能是非常复杂的任务,当考虑所有可能的功能时(级联样式,某些如果有几种不同的方式,符号实例等,可以设置属性。)