我有一个XSLT样式表,可以将纯文本符号转换为SVG。它工作正常,但只能处理带有一个项目的符号。这适用于例如:
"use strict";
app.controller('ProductController',function($scope,$http,Restangular,ProductService){
// get products
$scope.products = ProductService.list();
// create product
$scope.create = function(product) {
ProductService.create(product);
};
// Event Listeners
$scope.$on('product.create', function(product) {
$scope.products = ProductService.list();
console.log('product create');
});
});
当我想要使用多个这样的项目转换符号时,
GRAPHREP
PEN color:$000000 w:2pt
FILL color:$ff7f00
ELLIPSE x:0pt y:0pt rx:50pt ry:50pt
我将收到此错误:XPTY0004:不允许包含多个项目的序列作为local-name()的第一个参数。如何处理一件或多件物品?我在帖子的末尾添加了样式表。这可能是我对这个主题的最后一个问题。非常感谢你的帮助!
GRAPHREP
PEN color:$000000 w:2pt
FILL color:$ff7f00
ELLIPSE x:0pt y:0pt rx:50pt ry:50pt
PEN color:$000000 w:2pt
FILL color:$ff7f00
ELLIPSE x:0pt y:0pt rx:30pt ry:30pt
编辑:第二个输入的所需输出如下:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Ansatz mit Hilfe von
http://stackoverflow.com/questions/34682331/xslt-2-0-transform-notation-in-plain-text-to-svg -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:local="local"
exclude-result-prefixes="xs"
version="2.0"
xmlns:svg="http://www.w3.org/2000/svg">
<xsl:output indent="yes"/>
<xsl:variable name="drawing-text">
GRAPHREP
PEN color:$000000 w:2pt
FILL color:$ff7f00
ELLIPSE x:0pt y:0pt rx:50pt ry:50pt
PEN color:$000000 w:2pt
FILL color:$ff7f00
ELLIPSE x:0pt y:0pt rx:30pt ry:30pt
</xsl:variable>
<!--
<xsl:param name="drawing-text" />
-->
<!--matches sequences of UPPER-CASE letters -->
<xsl:variable name="label-pattern" select="'[A-Z]+'"/>
<!--matches the "attributes" in the line i.e. w:2pt,
has two capture groups (1) => attribute name, (2) => attribute value -->
<xsl:variable name="attribute-pattern" select="'\s?(\S+):(\S+)'"/>
<!--matches a line of data for the drawing text,
has two capture groups (1) => label, (2) attribute data-->
<xsl:variable name="line-pattern" select="concat('(', $label-pattern, ')\s(.*)\n?')"/>
<!-- Text in quotes holen-->
<xsl:variable name="text-pattern" select="'"(.*?)"'"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/" name="main">
<svg width="640" height="480">
<g>
<!-- Find the text patterns indicating the shape -->
<!--Replaced unparsed-text() with local variable for testing
select="unparsed-text('drawing.txt')" -->
<xsl:analyze-string select="$drawing-text"
regex="{concat('(', $label-pattern, ')\n((', $line-pattern, ')+)\n?')}">
<xsl:matching-substring>
<!--Convert text to XML -->
<xsl:variable name="drawing-markup" as="element()">
<!--Create an element for this group, using first matched pattern as the element name
(i.e. GRAPHREP => <GRAPHREP>) -->
<xsl:element name="{regex-group(1)}">
<!--split the second matched group for this shape into lines by breaking on newline-->
<xsl:variable name="lines" select="tokenize(regex-group(2), '\n')"/>
<xsl:for-each select="$lines">
<!--for each line, run through this process to create an element with attributes
(e.g. FILL color:$frf7f00 => <FILL color=""/>
-->
<xsl:analyze-string select="." regex="{$line-pattern}">
<xsl:matching-substring>
<!--create an element using the UPPER-CASE label starting the line -->
<xsl:element name="{regex-group(1)}">
<!-- capture each of the attributes -->
<xsl:analyze-string select="regex-group(2)" regex="\s?(\S+):(\S+)">
<xsl:matching-substring>
<!--convert foo:bar into attribute foo="bar",
translate $ => #
and remove the letters 'p' and 't' by translating into nothing"-->
<xsl:attribute name="{regex-group(1)}" select="translate(regex-group(2), '$pt', '#')"/>
</xsl:matching-substring>
<xsl:non-matching-substring/>
</xsl:analyze-string>
</xsl:element>
</xsl:matching-substring>
<xsl:non-matching-substring/>
</xsl:analyze-string>
</xsl:for-each>
</xsl:element>
</xsl:variable>
<!--Uncomment the copy-of below if you want to see the intermediate XML $drawing-markup-->
<!--<xsl:copy-of select="$drawing-markup"/>-->
<!-- Transform XML into SVG -->
<xsl:apply-templates select="$drawing-markup"/>
</xsl:matching-substring>
<xsl:non-matching-substring/>
</xsl:analyze-string>
</g>
</svg>
</xsl:template>
<!--==========================================-->
<!-- Templates to convert the $drawing-markup -->
<!--==========================================-->
<!--for supported shapes, create the element using
lower-case value, and change rectangle to rect
for the svg element name !!! if abfrage ob text-->
<xsl:template match="GRAPHREP[ELLIPSE | RECTANGLE | ROUNDRECT | LINE | TEXT]">
<xsl:if test="ELLIPSE | RECTANGLE | ROUNDRECT | LINE">
<xsl:element name="{replace(lower-case(local-name(ELLIPSE | RECTANGLE | ROUNDRECT | LINE)), 'rectangle|roundrect', 'rect', 'i')}">
<xsl:attribute name="id" select="concat('id_', generate-id())"/>
<xsl:apply-templates />
</xsl:element>
</xsl:if>
<xsl:if test="TEXT">
<xsl:element name="{lower-case(local-name(TEXT))}">
<xsl:attribute name="id" select="concat('id_', generate-id())"/>
<xsl:apply-templates />
<!-- Da muss der text aus den quotes rein -->
</xsl:element>
</xsl:if>
</xsl:template>
<xsl:template match="ELLIPSE | RECTANGLE | ROUNDRECT | LINE | TEXT"/>
<!-- Just process the content of GRAPHREP.
If there are multiple shapes and you want a new
<svg><g></g></svg> for each shape,
then move it from the template for "/" into this template-->
<xsl:template match="GRAPHREP/*">
<xsl:apply-templates select="@*"/>
</xsl:template>
<xsl:template match="PEN" priority="1">
<!--TODO: test if these attributes exist, if they do, do not create these defaults.
Hard-coding for now, to match desired output, since I don't know what the text
attributes would be, but could wrap each with <xsl:if test="not(@dasharray)">-->
<xsl:attribute name="stroke-dasharray" select="'null'"/>
<xsl:attribute name="stroke-linjoin" select="'null'"/>
<xsl:attribute name="stroke-linecap" select="'null'"/>
<xsl:apply-templates select="@*"/>
</xsl:template>
<!-- conterts @color => @stroke -->
<xsl:template match="PEN/@color">
<xsl:attribute name="stroke" select="."/>
</xsl:template>
<!--converts @w => @stroke-width -->
<xsl:template match="PEN/@w">
<xsl:attribute name="stroke-width" select="."/>
</xsl:template>
<!--converts @color => @fill and replaces $ with # -->
<xsl:template match="FILL/@color">
<xsl:attribute name="fill" select="translate(., '$', '#')"/>
</xsl:template>
<!--converts @h => @font-size !!noch mit text verbinden -->
<xsl:template match="FONT/@h">
<xsl:attribute name="font-size" select="."/>
</xsl:template>
<!--converts @color => @fill !!noch mit text verbinden -->
<xsl:template match="FONT/@color">
<xsl:attribute name="fill" select="translate(., '$', '#')"/>
</xsl:template>
<!-- converts @x => @cx with hard-coded values.
May want to use value from text, but matching your example-->
<xsl:template match="ELLIPSE/@x | ELLIPSE/@y">
<!--not sure if there was a relationship between ELLIPSE x:0pt y:0pt, and why 0pt would be 250,
but just an example...-->
<xsl:attribute name="c{name()}" select="."/>
</xsl:template>
<xsl:template match="RECTANGLE/@w | ROUNDRECT/@w">
<xsl:attribute name="{name()}idth" select="."/>
</xsl:template>
<xsl:template match="RECTANGLE/@h | ROUNDRECT/@h">
<xsl:attribute name="{name()}eight" select="."/>
</xsl:template>
<xsl:template match="LINE/@x | LINE/@y">
<xsl:attribute name="{name()}" select="."/>
</xsl:template>
<xsl:template match="TEXT/@x | TEXT/@y">
<xsl:attribute name="{name()}" select="."/>
</xsl:template>
</xsl:stylesheet>
SVG应该有2个不同的省略号。
答案 0 :(得分:1)
这是一个生成具有所需属性的两个SVG形状的示例:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Ansatz mit Hilfe von
http://stackoverflow.com/questions/34682331/xslt-2-0-transform-notation-in-plain-text-to-svg -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:local="local"
exclude-result-prefixes="xs"
version="2.0"
xmlns:svg="http://www.w3.org/2000/svg">
<xsl:output indent="yes"/>
<xsl:variable name="drawing-text">
GRAPHREP
PEN color:$000000 w:2pt
FILL color:$ff7f00
ELLIPSE x:0pt y:0pt rx:50pt ry:50pt
PEN color:$000000 w:2pt
FILL color:$ff7f00
ELLIPSE x:0pt y:0pt rx:30pt ry:30pt
</xsl:variable>
<!--
<xsl:param name="drawing-text" />
-->
<!--matches sequences of UPPER-CASE letters -->
<xsl:variable name="label-pattern" select="'[A-Z]+'"/>
<!--matches the "attributes" in the line i.e. w:2pt,
has two capture groups (1) => attribute name, (2) => attribute value -->
<xsl:variable name="attribute-pattern" select="'\s?(\S+):(\S+)'"/>
<!--matches a line of data for the drawing text,
has two capture groups (1) => label, (2) attribute data-->
<xsl:variable name="line-pattern" select="concat('(', $label-pattern, ')\s(.*)\n?')"/>
<!-- Text in quotes holen-->
<xsl:variable name="text-pattern" select="'"(.*?)"'"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/" name="main">
<svg width="640" height="480">
<g>
<!-- Find the text patterns indicating the shape -->
<!--Replaced unparsed-text() with local variable for testing
select="unparsed-text('drawing.txt')" -->
<xsl:analyze-string select="$drawing-text"
regex="{concat('(', $label-pattern, ')\n((', $line-pattern, ')+)\n?')}">
<xsl:matching-substring>
<!--Convert text to XML -->
<xsl:variable name="drawing-markup" as="element()">
<!--Create an element for this group, using first matched pattern as the element name
(i.e. GRAPHREP => <GRAPHREP>) -->
<xsl:element name="{regex-group(1)}">
<!--split the second matched group for this shape into lines by breaking on newline-->
<xsl:variable name="lines" select="tokenize(regex-group(2), '\n')"/>
<xsl:for-each select="$lines">
<!--for each line, run through this process to create an element with attributes
(e.g. FILL color:$frf7f00 => <FILL color=""/>
-->
<xsl:analyze-string select="." regex="{$line-pattern}">
<xsl:matching-substring>
<!--create an element using the UPPER-CASE label starting the line -->
<xsl:element name="{regex-group(1)}">
<!-- capture each of the attributes -->
<xsl:analyze-string select="regex-group(2)" regex="\s?(\S+):(\S+)">
<xsl:matching-substring>
<!--convert foo:bar into attribute foo="bar",
translate $ => #
and remove the letters 'p' and 't' by translating into nothing"-->
<xsl:attribute name="{regex-group(1)}" select="translate(regex-group(2), '$pt', '#')"/>
</xsl:matching-substring>
<xsl:non-matching-substring/>
</xsl:analyze-string>
</xsl:element>
</xsl:matching-substring>
<xsl:non-matching-substring/>
</xsl:analyze-string>
</xsl:for-each>
</xsl:element>
</xsl:variable>
<!--Uncomment the copy-of below if you want to see the intermediate XML $drawing-markup-->
<xsl:copy-of select="$drawing-markup"/>
<!-- Transform XML into SVG -->
<xsl:apply-templates select="$drawing-markup"/>
</xsl:matching-substring>
<xsl:non-matching-substring/>
</xsl:analyze-string>
</g>
</svg>
</xsl:template>
<!--==========================================-->
<!-- Templates to convert the $drawing-markup -->
<!--==========================================-->
<xsl:template match="GRAPHREP">
<xsl:for-each-group select="*" group-starting-with="PEN">
<xsl:apply-templates select="current-group()[not(self::PEN | self::FILL)]"/>
</xsl:for-each-group>
</xsl:template>
<xsl:template match="RECTANGLE | ROUNDRECT">
<rect>
<xsl:attribute name="id" select="concat('id_', generate-id())"/>
<xsl:apply-templates select="@*, current-group()[self::PEN], current-group()[self::FILL]"/>
</rect>
</xsl:template>
<xsl:template match="ELLIPSE | LINE | TEXT">
<xsl:element name="{lower-case(local-name())}">
<xsl:attribute name="id" select="concat('id_', generate-id())"/>
<xsl:apply-templates select="@*, current-group()[self::PEN], current-group()[self::FILL]/@*"/>
</xsl:element>
</xsl:template>
<xsl:template match="PEN" priority="1">
<!--TODO: test if these attributes exist, if they do, do not create these defaults.
Hard-coding for now, to match desired output, since I don't know what the text
attributes would be, but could wrap each with <xsl:if test="not(@dasharray)">-->
<xsl:attribute name="stroke-dasharray" select="'null'"/>
<xsl:attribute name="stroke-linjoin" select="'null'"/>
<xsl:attribute name="stroke-linecap" select="'null'"/>
<xsl:apply-templates select="@*"/>
</xsl:template>
<!-- conterts @color => @stroke -->
<xsl:template match="PEN/@color">
<xsl:attribute name="stroke" select="."/>
</xsl:template>
<!--converts @w => @stroke-width -->
<xsl:template match="PEN/@w">
<xsl:attribute name="stroke-width" select="."/>
</xsl:template>
<!--converts @color => @fill and replaces $ with # -->
<xsl:template match="FILL/@color">
<xsl:attribute name="fill" select="translate(., '$', '#')"/>
</xsl:template>
<!--converts @h => @font-size !!noch mit text verbinden -->
<xsl:template match="FONT/@h">
<xsl:attribute name="font-size" select="."/>
</xsl:template>
<!--converts @color => @fill !!noch mit text verbinden -->
<xsl:template match="FONT/@color">
<xsl:attribute name="fill" select="translate(., '$', '#')"/>
</xsl:template>
<!-- converts @x => @cx with hard-coded values.
May want to use value from text, but matching your example-->
<xsl:template match="ELLIPSE/@x | ELLIPSE/@y">
<!--not sure if there was a relationship between ELLIPSE x:0pt y:0pt, and why 0pt would be 250,
but just an example...-->
<xsl:attribute name="c{name()}" select="."/>
</xsl:template>
<xsl:template match="RECTANGLE/@w | ROUNDRECT/@w">
<xsl:attribute name="{name()}idth" select="."/>
</xsl:template>
<xsl:template match="RECTANGLE/@h | ROUNDRECT/@h">
<xsl:attribute name="{name()}eight" select="."/>
</xsl:template>
<xsl:template match="LINE/@x | LINE/@y">
<xsl:attribute name="{name()}" select="."/>
</xsl:template>
<xsl:template match="TEXT/@x | TEXT/@y">
<xsl:attribute name="{name()}" select="."/>
</xsl:template>
</xsl:stylesheet>