replaceSVG文档中的variables(在YAML中外部定义)

背景

有几个资源讨论了在SVG文档中使用variables,包括:

  • SVG中的variables:可能吗?
  • SVGvariables文本
  • 如何在SVG中定义或引用variables?
  • SVG:关于在variables文本值中使用<defs>和<use>
  • http://www.schepers.cc/w3c/svg/params/ref.html
  • https://www.w3.org/TR/2009/WD-SVGParamPrimer-20090430/#Introduction

尽pipe基于CSS,JavaScript和HTML的解决scheme对于Web来说非常有用,但在其他情况下,SVG是有用的,并且有能力为variables定义外部源也同样方便。

问题

SVG不提供定义SVG相关软件包(如Inkscape和rsvg-convert )可以重复使用的可重用文本的机制。 例如,以下将是非常棒的:

<?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg ...> <input href="definitions.svg" /> ... <text ...>${variableName}</text> </svg> 

image元素可以被重载来导入一个外部文件,但是这是一个黑客行为,并且不允许将文本值赋给variables名以便重用。

你如何从服务器上的外部文件(例如,一个YAML文件,但可能是一个数据库)读取variables名称和值,并在渲染之前replaceSVG文件中的variables?

另一个可能的解

在Inkscape中设置对象属性

在这里输入图像描述

保存它,我们会有类似的东西

 ... <text xml:space="preserve" style="font-style:normal;font-weight:normal;font-size:60px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;image-rendering:auto" x="262.91638" y="86.339157" id="mytest" sodipodi:linespacing="125%" inkscape:label="#myvar"><desc id="desc4150">The test object to replace with a var</desc><title id="title4148">myobj</title><tspan sodipodi:role="line" id="tspan4804" x="262.91638" y="86.339157" style="fill:#ffffff">sample</tspan></text> ... 

然后用键值对创建yaml文件

 myvar: hello world 

并解析SVG并替换值

 #! /usr/bin/env python import sys from xml.dom import minidom import yaml yvars = yaml.load(file('drawing.yaml', 'r')) xmldoc = minidom.parse('drawing.svg') for s in xmldoc.getElementsByTagName('text'): for c in s.getElementsByTagName('tspan'): c.firstChild.replaceWholeText(yvars[s.attributes['inkscape:label'].value[1:]]) print xmldoc.toxml() 

这些值将被替换

 <text id="mytest" inkscape:label="#myvar" sodipodi:linespacing="125%" style="font-style:normal;font-weight:normal;font-size:60px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;image-rendering:auto" x="262.91638" xml:space="preserve" y="86.339157"><desc id="desc4150">The test object to replace with a var</desc><title id="title4148">myobj</title> <tspan id="tspan4804" sodipodi:role="line" style="fill:#ffffff" x="262.91638" y="86.339157">hello world</tspan></text> 

一个可能的解决方案使用以

  • 我如何从Linux shell脚本解析YAML文件? (请参阅bash脚本 )
  • rpl包 (大多数发行版可用于字符串替换无正则表达式)
  • 庆典
  • grep,sed和awk

以下脚本:

  1. 以YAML格式读取变量定义。
  2. 循环当前目录中的所有文件。
  3. 检测文件是否有定义的变量。
  4. 用所有变量定义的值代替。
  5. 运行Inkscape将SVG文件转换为PDF。

有很多可以改进的地方,但是对于那些希望使用YAML在SVG文档中进行基本的变量替换的人来说,这应该是一个好的开始。

没有执行卫生措施,因此在运行此脚本之前确保输入是干净的。

 #!/bin/bash COMMAND="inkscape -z" DEFINITIONS=../variables.yaml # Parses YAML files. # # Courtesy of https://stackoverflow.com/a/21189044/59087 function parse_yaml { local prefix=$2 local s='[[:space:]]*' w='[a-zA-Z0-9_]*' fs=$(echo @|tr @ '\034') sed -ne "s|^\($s\):|\1|" \ -e "s|^\($s\)\($w\)$s:$s[\"']\(.*\)[\"']$s\$|\1$fs\2$fs\3|p" \ -e "s|^\($s\)\($w\)$s:$s\(.*\)$s\$|\1$fs\2$fs\3|p" $1 | awk -F$fs '{ indent = length($1)/2; vname[indent] = $2; for (i in vname) {if (i > indent) {delete vname[i]}} if (length($3) > 0) { vn=""; for (i=0; i<indent; i++) {vn=(vn)(vname[i])("_")} printf("%s%s%s=\"%s\"\n", "'$prefix'",vn, $2, $3); } }' } # Load variable definitions into this environment. eval $(parse_yaml $DEFINITIONS ) for i in *.svg; do INPUT=$i OUTPUT=$i # Replace strings in the file with values from the variable definitions. REPLACE_INPUT=tmp-$INPUT echo "Converting $INPUT..." # Subsitute if there's at least one match. if grep -q -o -m 1 -h \${.*} $INPUT; then cp $INPUT $REPLACE_INPUT # Loop over all the definitions in the file. for svgVar in $(grep -oh \${.*} $INPUT); do # Strip off ${} to get the variable name and then the value. varName=${svgVar:2:-1} varValue=${!varName} # Substitute the variable name for its value. rpl -fi "$svgVar" "$varValue" $REPLACE_INPUT > /dev/null 2>&1 done INPUT=$REPLACE_INPUT fi $COMMAND $INPUT -A m_k_i_v_$OUTPUT.pdf rm -f $REPLACE_INPUT done 

通过执行一般搜索并替换SVG文档,脚本不需要维护。 另外,变量可以在文件中的任何地方定义,不仅在text块内。

我看到的一种方法是使用Jinja模板在将其转换为PDF之前自定义Postscript文件。

你可以使用相同的方法。

把你的SVG文本文件作为Jinja模板,并把你的变量放在YAML中。

使用Python加载Jinja模板,然后应用在YAML文件中找到的变量