Using SVG in an XSL stylesheet - xslt

I am using Apache FOP to generate PDF's. My data is in a XML file and I use a XSL stylesheet to render it. I am having trouble using SVG in my stylesheet. I have create an SVG which is
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.0" width="400" height="400" id="svg2">
<path d="M200,200 L390,200 A190,190 0 0,1 200,390 z" fill="red" stroke="black" stroke-width="2" fill-opacity="0.5" stroke-linejoin="round" />
<path d="M200,200 L200,390 A190,190 0 0,1 10,200 z" fill="orange" stroke="black" stroke-width="2" fill-opacity="0.5" stroke-linejoin="round" />
<path d="M200,200 L10,200 A190,190 0 0,1 200,10 z" fill="yellow" stroke="black" stroke-width="2" fill-opacity="0.5" stroke-linejoin="round" />
<path d="M200,200 L200,10 A190,190 0 0,1 390,200 z" fill="green" stroke="black" stroke-width="2" fill-opacity="0.5" stroke-linejoin="round" />
</svg>
But how do I put it in the stylesheet. I have tried putting it in an <fo:instream-foreign-object> like
<fo:instream-foreign-object xmlns:svg="http://www.w3.org/2000/svg">
<svg:svg width="400" height="400">
<svg:path d="M200,200 L390,200 A190,190 0 0,1 200,390 z" fill="red" stroke="black" stroke-width="2" fill-opacity="0.5" stroke-linejoin="round" />
...
</svg:svg>
</fo:instream-foreign-object>
But this doesn't work. Does anyone know what I'm doing wrong?

He's my example of SVG inside FOP as a letter size background (with text 'background region'):
<fo:block-container absolute-position="absolute"
top="0in" left="0in" width="8.5in" height="11in"
content-height="scale-to-fit" content-width="scale-to-fit"
scaling="non-uniform"
background-position="center" background-repeat="no-repeat"
background-image="url(your_xml_file.svg)">
<fo:block>background region
</fo:block>
</fo:block-container>

its turns out I was doing it all wrong. The correct way to do it is rather than doing
<svg:path stroke="black" stroke-width="2" fill-opacity="0.5" stroke-linejoin="round" />
You need to draw the path like this
<svg:path stroke="black" stroke-width="2" fill-opacity="0.5" stroke-linejoin="round">
<xsl:attribute name="fill">red</xsl:attribute>
<xsl:attribute name="d">M200,200 L390,200 A190,190 0 0,1 200,390 z</xsl:attribute>
</svg:path>

Related

SVG created using Qt QPainter and QSvgGenerator clipped to viewport size

For a project, I am using QPainter with QSvgGenerator to create SVG as an output. The project basically produces basic class diagrams from C++ code. However, when I open the SVG using Google Chrome or any other web-browser, it is clipped according to the size of browser window without any scrollbars. On resizing window, further clipping occurs.
Related Code
QSvgGenerator temp_img;
//Save file as image
QString path = QFileDialog::getSaveFileName(w, ("Save as image"), "",
("SVG file (*.svg)"));
if (path.isEmpty())
return;
temp_img.setFileName(path);
QPainter painter;
painter.begin(&temp_img);
painter.setFont(QFont("Arial",12));
.
.
.
painter.end();
I have tried using setViewBox() but no effect.
I am using Qt for the first time so please try to be as elaborate as possible. I preferred SVG over Bitmaps because of Quality issues.
EDIT: Zooming out reveals the hidden parts.
As the OP didn't provide a MCVE, I prepared one on my own:
#include <QtWidgets>
#include <QtSvg/QSvgGenerator>
const int w = 100, h = 100;
void renderTest(QPainter &qPainter, double s)
{
qPainter.setTransform(QTransform().scale(s, s));
qPainter.setFont(QFont("Arial", 12));
qPainter.setPen(Qt::gray);
qPainter.drawRect(0, 0, w, h);
qPainter.setPen(Qt::black);
qPainter.drawLine(0.1 * w, 0.5 * h, 0.9 * w, 0.5 * h);
qPainter.drawLine(0.5 * w, 0.1 * h, 0.5 * w, 0.9 * h);
qPainter.drawLine(0.45 * w, 0.2 * h, 0.55 * w, 0.2 * h);
qPainter.drawLine(0.45 * w, 0.8 * h, 0.55 * w, 0.8 * h);
qPainter.drawLine(0.2 * w, 0.45 * h, 0.2 * w, 0.55 * h);
qPainter.drawLine(0.8 * w, 0.45 * h, 0.8 * w, 0.55 * h);
qPainter.drawText(QPointF(0.51 * w, 0.49 * h), "0");
qPainter.drawText(QPointF(0.51 * w, 0.79 * h), "-1");
qPainter.drawText(QPointF(0.51 * w, 0.19 * h), "+1");
qPainter.drawText(QPointF(0.21 * w, 0.49 * h), "-1");
qPainter.drawText(QPointF(0.81 * w, 0.49 * h), "+1");
qPainter.setPen(Qt::blue);
qPainter.drawEllipse(QPointF(0.5 * w, 0.5 * h), 0.3 * w, 0.3 * h);
}
void renderSvgFile(const QString &qFilePath, double s)
{
QSvgGenerator qSvgGen;
qSvgGen.setFileName(qFilePath);
qSvgGen.setSize(QSize(s * w, s * h));
renderTest(QPainter(&qSvgGen), s);
}
int main(int argc, char **argv)
{
qDebug() << "Qt Version:" << QT_VERSION_STR;
QApplication app(argc, argv);
// render tests
for (int i = 1; i <= 100; i *= 10) {
const QString qFilePath = QString("testQSvgGen.%1%2.svg").arg(i).arg("0%");
qDebug() << "Render" << qFilePath;
renderSvgFile(qFilePath, i * 0.1);
}
// done
return 0;
}
It generates three files:
testQSvgGen.10%.svg
testQSvgGen.100%.svg
testQSvgGen.1000%.svg
Although the images are written with different sizes, there is no noticable difference in the preview. The reason is that the preview scales the result to its own required resolution to fit the output into current Explorer icon size. (The same applies to the preview size on right size.)
In opposition to this, a Web Browser (Google Chrome in the above snapshot) considers the size setting of SVG.
These settings are
in testQSvgGen.10%.svg:
<svg width="3.52778mm" height="3.52778mm"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.2" baseProfile="tiny">
in testQSvgGen.100%.svg
<svg width="35.2778mm" height="35.2778mm"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.2" baseProfile="tiny">
in testQSvgGen.100%.svg
<svg width="352.778mm" height="352.778mm"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.2" baseProfile="tiny">
A closer look into the generated SVG-Code uncovered that the 3 files look very similar in general. The scaling which I forced by
qPainter.setTransform(QTransform().scale(s, s));
to adjust the graphics output to the intended image size is simply translated into a transform="matrix()" attribute with the scaling for each group (<g>).
So, I cannot confirm what OP complained:
The size set in QSvgGenerator::setSize() is considered in generated SVG files, and the browsers respect this setting (as expected).
Source code of generated testQSvgGen.10%.svg:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="352.778mm" height="352.778mm"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.2" baseProfile="tiny">
<title>Qt SVG Document</title>
<desc>Generated with Qt</desc>
<defs>
</defs>
<g fill="none" stroke="black" stroke-width="1" fill-rule="evenodd" stroke-linecap="square" stroke-linejoin="bevel" >
<g fill="none" stroke="#a0a0a4" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(10,0,0,10,0,0)"
font-family="Arial" font-size="12" font-weight="400" font-style="normal"
>
<rect x="0" y="0" width="100" height="100"/>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(10,0,0,10,0,0)"
font-family="Arial" font-size="12" font-weight="400" font-style="normal"
>
<polyline fill="none" vector-effect="none" points="10,50 90,50 " />
<polyline fill="none" vector-effect="none" points="50,10 50,90 " />
<polyline fill="none" vector-effect="none" points="45,20 55,20 " />
<polyline fill="none" vector-effect="none" points="45,80 55,80 " />
<polyline fill="none" vector-effect="none" points="20,45 20,55 " />
<polyline fill="none" vector-effect="none" points="80,45 80,55 " />
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(10,0,0,10,0,0)"
font-family="Arial" font-size="12" font-weight="400" font-style="normal"
>
<text fill="#000000" fill-opacity="1" stroke="none" xml:space="preserve" x="51" y="49" font-family="Arial" font-size="12" font-weight="400" font-style="normal"
>0</text>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(10,0,0,10,0,0)"
font-family="Arial" font-size="12" font-weight="400" font-style="normal"
>
<text fill="#000000" fill-opacity="1" stroke="none" xml:space="preserve" x="51" y="79" font-family="Arial" font-size="12" font-weight="400" font-style="normal"
>-1</text>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(10,0,0,10,0,0)"
font-family="Arial" font-size="12" font-weight="400" font-style="normal"
>
<text fill="#000000" fill-opacity="1" stroke="none" xml:space="preserve" x="51" y="19" font-family="Arial" font-size="12" font-weight="400" font-style="normal"
>+1</text>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(10,0,0,10,0,0)"
font-family="Arial" font-size="12" font-weight="400" font-style="normal"
>
<text fill="#000000" fill-opacity="1" stroke="none" xml:space="preserve" x="21" y="49" font-family="Arial" font-size="12" font-weight="400" font-style="normal"
>-1</text>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(10,0,0,10,0,0)"
font-family="Arial" font-size="12" font-weight="400" font-style="normal"
>
<text fill="#000000" fill-opacity="1" stroke="none" xml:space="preserve" x="81" y="49" font-family="Arial" font-size="12" font-weight="400" font-style="normal"
>+1</text>
</g>
<g fill="none" stroke="#0000ff" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(10,0,0,10,0,0)"
font-family="Arial" font-size="12" font-weight="400" font-style="normal"
>
<circle cx="50" cy="50" r="30"/>
</g>
</g>
</svg>
The specification of either size or view box is essential for a stand-alone SVG.
This is described in the SVG Specification by the W3C:
7.2 The initial viewport
The SVG user agent negotiates with its parent user agent to determine the viewport into which the SVG user agent can render the document. In some circumstances, SVG content will be embedded (by reference or inline) within a containing document. This containing document might include attributes, properties and/or other parameters (explicit or implicit) which specify or provide hints about the dimensions of the viewport for the SVG content. SVG content itself optionally can provide information about the appropriate viewport region for the content via the 'width' and 'height' XML attributes on the 'svg' element. The negotiation process uses any information provided by the containing document and the SVG content itself to choose the viewport location and size.
If the parent document format defines rules for referenced or embedded graphics content, then the negotiation process is determined by the parent document format specification. If the parent document is styled with CSS, then the negotiation process must follow the CSS rules for replaced elements. If there are CSS width and height properties (or corresponding XSL properties) on the referencing element (or rootmost 'svg' element for inline SVG content) that are sufficient to establish the width and height of the viewport, then these positioning properties establish the viewport's width, height, and aspect ratio.
If there is no parent document, the SVG user agent must use the 'width' and 'height' attributes on the rootmost 'svg' element element as the width and height for the viewport.
Note that the time at which the viewport size negotiation is finalized is implementation-specific. Authors who need to be sure of the dimensions of the viewport should do so with load-event or resize-event handlers.
I made some examples to illustrate this.
A test file without width, height, and viewBox – test.svg:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.2" baseProfile="tiny">
<title>SVG Test</title>
<desc>A test to illustrate the role of width and height</desc>
<rect x="0" y="0" width="100" height="100"
style="stroke-width:1;stroke:#888;fill:none"/>
<circle cx="50" cy="50" r="30"
style="stroke-width:1;stroke:#000;fill:none"/>
</svg>
Output in Google Chrome:
[![Snapshot of test.svg in Google Chrome][1]][1]
[![Snapshot of test.svg in Google Chrome (after resize)][2]][2]
Output in Firefox:
[![Snapshot of test.svg in Firefox][3]][3]
Although, the browser seems to render correctly, the graph size isn't considered correctly. (No vertical scrollbar appears although the SVG contents doesn't fit into view.)
Providing a view port (width and height) – test.100x100.svg:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="100" height="100"
viewBox="0 0 100 100"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.2" baseProfile="tiny">
<title>SVG Test</title>
<desc>A test to illustrate the role of width and height</desc>
<rect x="0" y="0" width="100" height="100"
style="stroke-width:1;stroke:#888;fill:none"/>
<circle cx="50" cy="50" r="30"
style="stroke-width:1;stroke:#000;fill:none"/>
</svg>
Output in Google Chrome:
[![Snapshot of test.100x100.svg in Google Chrome][4]][4]
[![Snapshot of test.100x100.svg in Google Chrome (after resize)][5]][5]
The same file with reduced width and height – test.50x50.svg:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="50" height="50"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.2" baseProfile="tiny">
<title>SVG Test</title>
<desc>A test to illustrate the role of width and height</desc>
<rect x="0" y="0" width="100" height="100"
style="stroke-width:1;stroke:#888;fill:none"/>
<circle cx="50" cy="50" r="30"
style="stroke-width:1;stroke:#000;fill:none"/>
</svg>
Output in Google Chrome:
[![Snapshot of test.50x50.svg in Google Chrome][6]][6]
The initial view size is reduced.
The graphic output is clipped against width and height.
Next, I added a viewBox attribute – test.50x50.view100x100.svg:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="50" height="50"
viewBox="0 0 100 100"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.2" baseProfile="tiny">
<title>SVG Test</title>
<desc>A test to illustrate the role of width and height</desc>
<rect x="0" y="0" width="100" height="100"
style="stroke-width:1;stroke:#888;fill:none"/>
<circle cx="50" cy="50" r="30"
style="stroke-width:1;stroke:#000;fill:none"/>
</svg>
Output in Google Chrome:
[![Snapshot of test.50x50.view100x100.svg in Google Chrome][7]][7]
The view is still reduced but the graphics contents is scaled to fit into view.
What happens when width and height are missing? – test.view100x100.svg:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
viewBox="0 0 100 100"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.2" baseProfile="tiny">
<title>SVG Test</title>
<desc>A test to illustrate the role of width and height</desc>
<rect x="0" y="0" width="100" height="100"
style="stroke-width:1;stroke:#888;fill:none"/>
<circle cx="50" cy="50" r="30"
style="stroke-width:1;stroke:#000;fill:none"/>
</svg>
Output in Google Chrome:
[![Snapshot of test.view100x100.svg in Google Chrome][8]][8]
[![Snapshot of test.view100x100.svg in Google Chrome (after resize)][9]][9]
The output is scaled to fit in the browser view.
This can be compiled to the following rule of thumbs:
The viewBox defines something like a clip space for the graphical contents.
The width and height provide a hint for the output size the renderer should use.
If viewBox is missing then it is set to viewBox="0 0 width height".
If width and height are missing the renderer is free to chose it on its own.
At least, either width and height, or viewBox should be provided.
The QSvgGenerator provides the following properties to control width, height, and viewBox:
size : QSize
This property holds the size of the generated SVG drawing
By default this property is set to QSize(-1, -1), which indicates that the generator should not output the width and height attributes of the element.
Note: It is not possible to change this property while a QPainter is active on the generator.
viewBox : QRectF
This property holds the viewBox of the generated SVG drawing
By default this property is set to QRect(0, 0, -1, -1), which indicates that the generator should not output the viewBox attribute of the element.
Note: It is not possible to change this property while a QPainter is active on the generator.

For postproc of graphviz svg I now uses several perl exps with differing input opts. How to combine?

I use graphviz to generate SVG graphs, and use some perl expressions (some -lane, some -0pe) to post-process/slim the dot output.
The following shell/perl command pipeline will:
convert some <polygons into <rect, because dot outputs even perfect rectangles as polygons.
convert some more polygons, because "clusters" -though rectangular- are layed out differently to "normal" nodes
removes/rounds some ".9999999" fractions somehow resulting from the first 2 commands...
rewrites straight lines (h+v) from <path to <line
remove empty groups resulting from invisible nodes and paths still being "rendered" to the SVG.
Ultimately make the file smaller and also easier to read.
How would I optimize this script and/or compact it into less statements under one perl invocation?
$ cat Graph.dot.svg |
perl -lane '# Rectangular Nodes: Polygons like DR-DL-UL-UR-DR
/^<polygon( .* )points="([-\d.]*),([-\d.]*) ([-\d.]*),\3 \4,([-\d.]*) \2,\5 \2,\3"(.*)$/
and do {
$x=($2<$4?$2:$4); $y=($3<$5?$3:$5);
$w=abs($2-$4); $h=abs($3-$5);
print "<rect$1x=\"$x\" y=\"$y\" width=\"$w\" height=\"$h\"$6";
} or print $_;' |
perl -lane '# Cluster Nodes -also rects-, but layed out differntly:
/^<polygon( .* )points="([-\d.]*),([-\d.]*) \2,([-\d.]*) ([-\d.]*),\4 \5,\3 \2,\3"(.*)$/
and do {
$x=($2<$5?$2:$5); $y=($3<$4?$3:$4);
$w=abs($2-$5); $h=abs($3-$4);
print "<rect$1x=\"$x\" y=\"$y\" width=\"$w\" height=\"$h\"$6";
} or print $_;
' | perl -pe '# Rounds ".999999" and "\d*[36]99+7" "errors"
/^<rect/ and s/([0-9]+\.)99+/$1+1/e;s/([36])99+7/$1+1/e
' | perl -lane '# Straight vertical lines as paths -> "<line"
print /^<path( .* )d="M([-\d.]*),([-\d.]*)C(([-\d.]*),\3 ?){3}"(.*)$/
?"<line$1x1=\"$2\" y1=\"$3\" x2=\"$5\" y2=\"$3\" stroke-width=\"2\"$6" : $_;
' | perl -lane '# Straight horizontal lines as paths -> "<line"
print /^<path( .* )d="M([-\d.]*),([-\d.]*)C(\2,([-\d.]*) ?){3}"(.*)$/
?"<line$1x1=\"$2\" y1=\"$3\" x2=\"$2\" y2=\"$5\" stroke-width=\"2\"$6" : $_;
' | perl -0777 -pe '
s/^<!-- [^ ]\* -->\s<g [^<]*<title>[^>]*>\s<\/g>$//mg' > Output.dot.svg
Example Input data below generated from graph:
graph G {
node[shape=box,height=0,width=0,margin=0]
subgraph cluster_1 {
start -- b1;
}
rank=same{b1 -- end};
end [shape=circle];
}
with either dot -Tsvg or online here(viz.je)
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="89pt" height="105pt"
viewBox="0.00 0.00 89.29 105.39" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 101.388)">
<polygon fill="white" stroke="none" points="-4,4 -4,-101.388 85.2939,-101.388 85.2939,4 -4,4"/>
<g id="clust1" class="cluster"><title>cluster_1</title>
<polygon fill="none" stroke="black" points="8,-56.5878 8,-89.3878 48,-89.3878 48,-56.5878 8,-56.5878"/>
</g>
<g id="node1" class="node"><title>start</title>
<polygon fill="none" stroke="black" points="40.1012,-81.2889 15.8988,-81.2889 15.8988,-64.6866 40.1012,-64.6866 40.1012,-81.2889"/>
<text text-anchor="middle" x="28" y="-68.7878" font-family="Times,serif" font-size="14.00">start</text>
</g>
<g id="node2" class="node"><title>b1</title>
<polygon fill="none" stroke="black" points="35,-22.5951 21,-22.5951 21,-5.9927 35,-5.9927 35,-22.5951"/>
<text text-anchor="middle" x="28" y="-10.0939" font-family="Times,serif" font-size="14.00">b1</text>
</g>
<!-- start--b1 -->
<g id="edge1" class="edge"><title>start--b1</title>
<path fill="none" stroke="black" d="M28,-64.576C28,-53.7707 28,-33.796 28,-22.8884"/>
</g>
<g id="node3" class="node"><title>end</title>
<ellipse fill="none" stroke="black" cx="67" cy="-14.2939" rx="14.0907" ry="14.0907"/>
<text text-anchor="middle" x="67" y="-10.0939" font-family="Times,serif" font-size="14.00">end</text>
</g>
<!-- b1--end -->
<g id="edge2" class="edge"><title>b1--end</title>
<path fill="none" stroke="black" d="M35.0078,-14.2939C40.8397,-14.2939 46.6716,-14.2939 52.5035,-14.2939"/>
</g>
</g>
</svg>
The result after feeding the above input into the perl pipeline (Notice all the polygons and paths have been converted to rectangles and lines.)
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="89pt" height="105pt"
viewBox="0.00 0.00 89.29 105.39" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 101.388)">
<rect fill="white" stroke="none" x="-4" y="-101.388" width="89.2939" height="105.388"/>
<g id="clust1" class="cluster"><title>cluster_1</title>
<rect fill="none" stroke="black" x="8" y="-89.3878" width="40" height="32.8"/>
</g>
<g id="node1" class="node"><title>start</title>
<rect fill="none" stroke="black" x="15.8988" y="-81.2889" width="24.2024" height="16.6023"/>
<text text-anchor="middle" x="28" y="-68.7878" font-family="Times,serif" font-size="14.00">start</text>
</g>
<g id="node2" class="node"><title>b1</title>
<rect fill="none" stroke="black" x="21" y="-22.5951" width="14" height="16.6024"/>
<text text-anchor="middle" x="28" y="-10.0939" font-family="Times,serif" font-size="14.00">b1</text>
</g>
<!-- start--b1 -->
<g id="edge1" class="edge"><title>start--b1</title>
<line fill="none" stroke="black" x1="28" y1="-64.576" x2="28" y2="-22.8884" stroke-width="2"/>
</g>
<g id="node3" class="node"><title>end</title>
<ellipse fill="none" stroke="black" cx="67" cy="-14.2939" rx="14.0907" ry="14.0907"/>
<text text-anchor="middle" x="67" y="-10.0939" font-family="Times,serif" font-size="14.00">end</text>
</g>
<!-- b1--end -->
<g id="edge2" class="edge"><title>b1--end</title>
<line fill="none" stroke="black" x1="35.0078" y1="-14.2939" x2="52.5035" y2="-14.2939" stroke-width="2"/>
</g>
</g>
</svg>

Regular expression to delete everything in a file except a string

I'm trying to parse some svg coordinates with Notepad++. I would like take the coordinate set of each layer and put the coordinates inside [] to make it ready to be used in a javascript array.
The svg file looks like this:
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 14.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 43363) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="800px"
height="900px" viewBox="0 0 800 900" enable-background="new 0 0 800 900" xml:space="preserve">
<g id="Layer_3">
<polyline fill="none" stroke="#0000FF" stroke-width="3" points="33,108 66,141 99,174 99,207 132,207 165,207 165,240 "/>
</g>
<g id="Layer_4">
<polyline fill="none" stroke="#0000FF" stroke-width="3" points="132,306 165,306 165,339 165,372 132,405 99,405 99,438 132,438
165,438 "/>
</g>
<g id="Layer_5">
<polyline fill="none" stroke="#0000FF" stroke-width="3" points="198,339 231,339 264,372 297,372 330,405 363,438 396,438 "/>
</g>
<g id="Layer_6">
<polyline fill="none" stroke="#0000FF" stroke-width="3" points="198,174 198,273 231,306 264,306 "/>
</g>
<g id="Layer_7">
<polyline fill="none" stroke="#0000FF" stroke-width="3" points="231,174 231,240 264,273 297,273 "/>
</g>
<g id="Layer_9">
<polyline fill="none" stroke="#0000FF" stroke-width="3" points="396,306 462,306 495,339 495,372 528,405 528,438 561,438
594,471 "/>
</g>
<g id="Layer_10">
<polyline fill="none" stroke="#0000FF" stroke-width="3" points="660,504 561,504 495,504 "/>
</g>
</svg>
I would like the result to look something like this:
[33,108 66,141 99,174 99,207 132,207 165,207 165,240]
[132,306 165,306 165,339 165,372 132,405 99,405 99,438 132,438 165,438]
[198,339 231,339 264,372 297,372 330,405 363,438 396,438]
[198,174 198,273 231,306 264,306]
[231,174 231,240 264,273 297,273]
[396,306 462,306 495,339 495,372 528,405 528,438 561,438 594,471]
[660,504 561,504 495,504]
I'm quite new to regular expressions, but here's my feeble attempt:
search for: .+points="(.+")
replace with: [$1]
I'm stuck because the search part doesn't seem to search lines above the "points" string. How can I get rid of everything but the coordinates, even if there is garbage much higher in the document?
First of all I have to agree in general with Ken White about not parsing XML with regexes. But if you want a quick and dirty solution in Notepad++ try this one (don't forget to check the option ". matches newline"):
Find:
.+?points="(.+?)\s*"
Replace:
[$1]\n\n
This will almost give you the anticipated result (you will still have to manually remove some trailing characters).

How can I keep my content from being cutoff with apache fop?

I am going through the Apache FOP quickstart. From the command line I am converting a simple xml file that contains an svg element and converting it to a pdf file. I am able to do this, but the image generated by the svg is being cut off. I am new to XSL-FO & Apache FOP, but I did check out the w3c documentation of properties. Now I'm even more confused, unfortunately. I have tried the following with no luck: altering the width & height properties in the svg itself; setting page-height & page-width to "auto" in the simple page master element; eliminating the margin property. I didn't see anything indicating the region-body starts with some default size.
Here is the xml:
<chart>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="600" height="100">
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="2" fill="red" />
<circle cx="100" cy="100" r="40" stroke="black" stroke-width="2" fill="green" />
</svg>
And here's the xsl:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<fo:root>
<fo:layout-master-set>
<fo:simple-page-master master-name="A4-portrait"
margin="10">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait">
<fo:flow flow-name="xsl-region-body">
<fo:block>
<fo:instream-foreign-object xmlns:svg="http://www.w3.org/2000/svg" content-width="600" content-height="300">
<svg:svg>
<xsl:copy-of select="/chart/svg:svg"/>
</svg:svg>
</fo:instream-foreign-object>
</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
</xsl:stylesheet>
The image is supposed to show a red & green circle overlapping, but it's only showing the upper left corner of the green one. I expect there's a property in the block element I am missing, but I don't know which. I looks like the block is limited to a 100px x 100px size.
What am I missing of the properties and how can I get the whole svg image to show properly (two full circles overlapping)?
Thanks,
Brandt
PS: I would have sent an image showing the problem, but I don't have a high enough reputation.
Errors are the specification of size with no units in FO in three places (margin, content-width and content-height). Also the SVG as stated in the comment above has a height of 100 which exceeds half of the green circle.
Correcting these and showing just the FO:
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="A4-portrait">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrait">
<fo:flow flow-name="xsl-region-body">
<fo:block>
<fo:instream-foreign-object xmlns:svg="http://www.w3.org/2000/svg">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="600" height="200">
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="2" fill="red" />
<circle cx="100" cy="100" r="40" stroke="black" stroke-width="2" fill="green" />
</svg>
</fo:instream-foreign-object>
</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
This shows the complete SVG image in your output.

XSLT - Combining 2 nodes with attributes into 1

I have the following source XML:
<?xml version="1.0" encoding="utf-8" ?>
<svg width="800" height="600" xml:id="pg1">
<g class="foreground">
<text transform="translate(163,90)
rotate(0.000,219.664,8.938)
scale(1.000,1.000)"
RotationPoint="(320.000000,240.000000)"
xml:id="anno1"
visible="1" editwidth="439.33" editheight="17.88"
forcewidth="0" forceheight="0" language_direction="1"
textdirection="0" theme_anno_style="0">
<tspan justification="left"
line-spacing="1.00" prepara-spacing="1.00"
bullet="0">
<tspan>
<tspan fill="#000000" font-size="16.000"
font-family="Arial"
char-transform="0.00 1.00 0.00 0.00 0.00 1.00"
textLength="439.33" y="14.48" x="0.00">
It is not a book you can curl up at night with</tspan>
</tspan>
</tspan>
</text>
</g>
</svg>
I want to transform it to this:
<svg:page id="page0.svg">
<svg:rect id="page0.svg_BG_Rect" fill="#ffffff" x="0" y="0" width="800.00" height="600.00"/>
<svg:textarea fill="none" font-weight="normal" font-stretch="normal" font-style="normal" font-family="" font-size="0.00" x="163.00" y="90.00" width="483.26" height="19.66" transform="translate(0,0) rotate(0,320,240)" id="anno1">
<svg:tspan fill="#000000" font-weight="normal" font-stretch="normal" font-style="normal" font-family="Arial" font-size="16.00" id="para1" text-align="start">
<svg:tspan fill="#000000" font-weight="normal" font-stretch="normal" font-style="normal" font-family="Arial" font-size="16.00">
<svg:tspan fill="#000000" font-weight="normal" font-stretch="normal" font-style="normal" font-family="Arial" font-size="16.00">
<![CDATA[ It is not a book you can curl up at night with]]>
</svg:tspan>
</svg:tspan>
<svg:tbreak/>
</svg:tspan>
</svg:textarea>
</svg:page>
I am told this is best done using XSLT, but the example/tutorial I have seen show simple 1 to 1 transforms, that could probably be done using text search/replace (Ok, slight exaggeration).
The above is just one example, there are many more, but I could really do with a starter XSLT to give me a start.
It is a bit ambiguous from your example what you want, as some of the attribute values have no clear origin and would need to be hardcoded or calculated somehow.
That said, I think the following solution gives you the structure you are after. (Note that it's missing the finer details, like number formatting.)
Given the following input XML:
<?xml version="1.0" encoding="utf-8" ?>
<svg width="800" height="600" xml:id="pg1">
<g class="foreground">
<text transform="translate(163,90)
rotate(0.000,219.664,8.938)
scale(1.000,1.000)"
RotationPoint="(320.000000,240.000000)"
xml:id="anno1"
visible="1" editwidth="439.33" editheight="17.88"
forcewidth="0" forceheight="0" language_direction="1"
textdirection="0" theme_anno_style="0">
<tspan justification="left"
line-spacing="1.00" prepara-spacing="1.00"
bullet="0">
<tspan>
<tspan fill="#000000" font-size="16.000"
font-family="Arial"
char-transform="0.00 1.00 0.00 0.00 0.00 1.00"
textLength="439.33" y="14.48" x="0.00">
It is not a book you can curl up at night with
</tspan>
</tspan>
</tspan>
</text>
</g>
</svg>
This XSL stylesheet:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:svg="http://www.w3.org/2000/svg">
<xsl:output method="xml" version="1.0" indent="yes" cdata-section-elements="svg:tspan" omit-xml-declaration="yes"/>
<xsl:strip-space elements="*"/>
<!-- Get the fill attribute for svg:tspan from the innermost tspan element
(i.e. the tspan element with no tspan children). -->
<xsl:variable name="fill">
<xsl:value-of select="//tspan[not(tspan)]/#fill"/>
</xsl:variable>
<!-- Get the font-family attribute for svg:tspan from the innermost tspan element. -->
<xsl:variable name="font-family">
<xsl:value-of select="//tspan[not(tspan)]/#font-family"/>
</xsl:variable>
<!-- Get the font-size attribute for svg:tspan from the innermost tspan element. -->
<xsl:variable name="font-size">
<xsl:value-of select="//tspan[not(tspan)]/#font-size"/>
</xsl:variable>
<!-- Create the transform attribute by parsing the RotationPoint attribute of
the text element. -->
<xsl:variable name="transform">
<xsl:text>translate(0,0) rotate(0,</xsl:text>
<xsl:call-template name="substring-between">
<xsl:with-param name="substr" select="//text/#RotationPoint"/>
<xsl:with-param name="after" select=" '(' "/>
<xsl:with-param name="before" select=" ',' "/>
</xsl:call-template>
<xsl:text>,</xsl:text>
<xsl:call-template name="substring-between">
<xsl:with-param name="substr" select="//text/#RotationPoint"/>
<xsl:with-param name="after" select=" ',' "/>
<xsl:with-param name="before" select=" ')' "/>
</xsl:call-template>
<xsl:text>)</xsl:text>
</xsl:variable>
<!-- A helper function to find the string between two strings. -->
<xsl:template name="substring-between">
<xsl:param name="substr"/>
<xsl:param name="after"/>
<xsl:param name="before"/>
<xsl:value-of select="substring-after(substring-before($substr, $before), $after)"/>
</xsl:template>
<!-- Create the svg:page and svg:rect elements. Attributes hard-coded when it's not clear where they come from. -->
<xsl:template match="svg">
<svg:page xmlns:svg="http://www.w3.org/2000/svg" id="page0.svg">
<svg:rect id="page0.svg_BG_Rect" fill="#ffffff" x="0" y="0" width="{#width}" height="{#height}">
<xsl:apply-templates/>
</svg:rect>
</svg:page>
</xsl:template>
<!-- Create the svg:textarea element. Attributes hardcoded when it's not clear where they come from. -->
<xsl:template match="text">
<svg:textarea fill="none" font-weight="normal" font-stretch="normal" font-style="normal" font-family="" font-size="0.00" x="163.00" y="90.00" width="{#editwidth}" height="{#editheight}" transform="{$transform}" id="{#xml:id}">
<xsl:apply-templates/>
</svg:textarea>
</xsl:template>
<!-- Change the tspan elements to svg:tspan elements, using attributes from the innermost tspan element (which were put into variables earlier). Only the outermost tspan element has the id and text-align attributes. -->
<xsl:template match="tspan">
<svg:tspan fill="{$fill}" font-weight="normal" font-stretch="normal" font-style="normal" font-family="{$font-family}" font-size="{$font-size}">
<xsl:if test="not(parent::tspan)">
<xsl:attribute name="id">para1</xsl:attribute>
<xsl:attribute name="text-align">start</xsl:attribute>
</xsl:if>
<xsl:apply-templates/>
</svg:tspan>
</xsl:template>
</xsl:stylesheet>
Outputs this XML:
<svg:page xmlns:svg="http://www.w3.org/2000/svg" id="page0.svg">
<svg:rect id="page0.svg_BG_Rect"
fill="#ffffff"
x="0"
y="0"
width="800"
height="600">
<svg:textarea fill="none"
font-weight="normal"
font-stretch="normal"
font-style="normal"
font-family=""
font-size="0.00"
x="163.00"
y="90.00"
width="439.33"
height="17.88"
transform="translate(0,0) rotate(0,320.000000,240.000000)"
id="anno1">
<svg:tspan fill="#000000"
font-weight="normal"
font-stretch="normal"
font-style="normal"
font-family="Arial"
font-size="16.000"
id="para1"
text-align="start">
<svg:tspan fill="#000000"
font-weight="normal"
font-stretch="normal"
font-style="normal"
font-family="Arial"
font-size="16.000">
<svg:tspan fill="#000000"
font-weight="normal"
font-stretch="normal"
font-style="normal"
font-family="Arial"
font-size="16.000"><![CDATA[
It is not a book you can curl up at night with
]]></svg:tspan>
</svg:tspan>
</svg:tspan>
</svg:textarea>
</svg:rect>
</svg:page>