【问题标题】:Selecting Style Attributes in SVG Files with R使用 R 在 SVG 文件中选择样式属性
【发布时间】:2014-07-07 16:52:23
【问题描述】:

我想使用 R 读取 SVG 文件,根据数据值更改 SVG 文件,然后将 SVG 导出为光栅图像,例如 png。

通过一些研究,我已经确定 SVGMapping 包本来可以帮助我到达那里,但是这个包已从 CRAN 存储库中删除,因此我对将它用于我可能依赖的任何东西都持谨慎态度。

因为 SVG 是 XML,所以我的计划是使用 XML 包来更改我的 SVG 文件的属性。然后我想使用 shell 函数调用 inkscape 将 SVG 转换为 PNG。

我在导航 XML 结构时遇到问题。正如您在下面的 SVG 中看到的,我创建了三个不同颜色的矩形。我想用 R 改变颜色。

我可以阅读 SVG 并使用以下内容导航到属性:

doc <- xmlTreeParse("c:\\Temp\\drawing.svg", getDTD = F)
doc$children$svg$children$g$children[1]$rect$attributes

然后我可以使用以下方法提取所有样式信息:

doc$children$svg$children$g$children[1]$rect$attributes["style"]

但是这样的结果只是一个包含填充、描边、不透明度等值的字符串。

"fill:#00ffff;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" 

有没有办法选择一个样式属性,例如填充,这样我就可以输入一个新的颜色代码?

我猜我最终可能会使用基于正则表达式的东西,但我想我会问是否有替代(即更简单!)的方式来浏览样式属性。

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="744.09448819"
   height="1052.3622047"
   id="svg2"
   version="1.1"
   inkscape:version="0.48.2 r9819"
   sodipodi:docname="New document 1">
  <defs
     id="defs4" />
  <sodipodi:namedview
     id="base"
     pagecolor="#ffffff"
     bordercolor="#666666"
     borderopacity="1.0"
     inkscape:pageopacity="0.0"
     inkscape:pageshadow="2"
     inkscape:zoom="0.53183594"
     inkscape:cx="375"
     inkscape:cy="520"
     inkscape:document-units="px"
     inkscape:current-layer="layer1"
     showgrid="false"
     inkscape:window-width="739"
     inkscape:window-height="558"
     inkscape:window-x="175"
     inkscape:window-y="175"
     inkscape:window-maximized="0" />
  <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" />
        <dc:title></dc:title>
      </cc:Work>
    </rdf:RDF>
  </metadata>
  <g
     inkscape:label="Layer 1"
     inkscape:groupmode="layer"
     id="layer1">
    <rect
       style="fill:#ff0000;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
       id="rect2985"
       width="180.50679"
       height="165.46455"
       x="30.084465"
       y="225.03938"
       rx="0"
       ry="0" />
    <rect
       style="fill:#00ff00;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
       id="rect2985-1"
       width="180.50679"
       height="165.46455"
       x="312.12634"
       y="230.68022"
       rx="0"
       ry="0" />
    <rect
       style="fill:#00ffff;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
       id="rect2985-7"
       width="180.50679"
       height="165.46455"
       x="118.45758"
       y="456.31369"
       rx="0"
       ry="0" />
  </g>
</svg>

【问题讨论】:

  • 您愿意修改 SVG 文件吗?您可以将样式替换为更易于解析的属性。

标签: xml r svg


【解决方案1】:

就目前而言,您需要在 XML 包之外处理 style。在这种情况下,您可以拆分 ";"":"

xData <- xmlParse("c:\\Temp\\drawing.svg")
out <- lapply(xData["//svg:rect"], xmlGetAttr, name = "style")
out <- sapply(out, strsplit, ";")
out <- lapply(out, strsplit, ":")
out <- lapply(out, function(x){
  sapply(x, function(y){`names<-`(y[2], y[1])})
}
)
out <- `names<-`(do.call(rbind.data.frame, out), names(out[[1]]))

out$fill <- "#000000"
out <- apply(out, 1, function(x) paste(names(out), x, sep = ':'))
out <- apply(out, 2, function(x) paste(x, collapse = ";"))

# remove old styles
lapply(xData["//svg:rect"], removeAttributes, .attrs = 'style')
# add new styles

mapply(addAttributes, node = xData["//svg:rect"], style = out)

> xData["//svg:rect"]
[[1]]
<rect id="rect2985" width="180.50679" height="165.46455" x="30.084465" y="225.03938" rx="0" ry="0" style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"/> 

[[2]]
<rect id="rect2985-1" width="180.50679" height="165.46455" x="312.12634" y="230.68022" rx="0" ry="0" style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"/> 

[[3]]
<rect id="rect2985-7" width="180.50679" height="165.46455" x="118.45758" y="456.31369" rx="0" ry="0" style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"/> 

attr(,"class")
[1] "XMLNodeSet"

【讨论】:

  • 这看起来很积极,但我猜我仍然会遇到将任何更改重新合并到原始 SVG 的问题
  • @Tumbledown 您可以更改属性,然后使用 removeAttributesaddAttributes 将它们添加回 XML
  • 谢谢@jdharrison,我仍然在语法正确时遇到问题。我不希望您为我编写代码,但您知道一个不错的示例/教程,其中涵盖了使用 removeAttributes 和 addAttributes 吗?我已经阅读了 XML 指南,但它有点……实用。我开始认为正则表达式可能更容易!
  • 哦,我尝试按照@robert-longson 的建议修改 SVG 文件。这似乎确实简化了不必将字符串分开并且仍然可以很好地解释 SVG 的问题。
  • 我同意在这种情况下我只会使用正则表达式。
猜你喜欢
  • 2014-04-10
  • 1970-01-01
  • 2017-10-05
  • 1970-01-01
  • 2012-08-21
  • 1970-01-01
  • 1970-01-01
  • 2014-09-27
  • 1970-01-01
相关资源
最近更新 更多