【问题标题】:XSLT delete inside <g> element of anXSLT 在 <g> 元素内删除
【发布时间】:2013-12-12 15:40:52
【问题描述】:

我有一些看起来像这样的 svg 代码:

<?xml version="1.0"?>
 <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px">
<g id="outer">
    <g id="inner-1">
        <defs>
               <rect/>
        </defs>
        <clipPath></clipPath>
        <polygon/>
    </g>
       <text>Some</text>
       <text>Text</text>
    <g id="inner-2">
        <defs>
               <rect/>
        </defs>
        <clipPath></clipPath>
       <polygon/>
   </g>
       <text>Some</text>
       <text>Text</text>
       <text>Some</text>
       <text>Text</text>
    <g id="inner-3">
        <defs>
               <rect/>
        </defs>
        <clipPath></clipPath>
       <polygon/>
   </g>
  <text>Keep this text</text>
  <text>Keep this text</text>
</g>
</svg>

如何删除第二次和第三次出现的内部&lt;g&gt; 标记和第一个内部&lt;g&gt; 之后的&lt;text&gt; 标记,以及第二个内部&lt;g&gt; 之后的&lt;text&gt; 标记。我可以在&lt;g&gt;tag 之后有nth 个&lt;text&gt; 标签,但我将始终“删除”(不是通过覆盖身份转换来选择)第二个内部&lt;g&gt; 标签和之前的文本,并且第三个内部 &lt;g&gt; 标签和之前的文本。 我只想要第 1 次出现的内部 '' 标记和第 3 次出现的内部 '' 标记之后的 &lt;text&gt; 标记。它应该是这样的:

<?xml version="1.0"?>
 <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px">
<g id="outer">
    <g id="inner-1">
        <defs>
               <rect/>
        </defs>
        <clipPath></clipPath>
        <polygon/>
    </g>
  <text>Keep this text</text>
  <text>Keep this text</text>
</g>
</svg>

这是我想出的:

 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg">

   <xsl:template match="node()|@*">
   <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
   </xsl:copy>
   </xsl:template>

<!-- I don't know how to select preceding text -->
<xsl:template match="/svg/g/g[2]"/>
<!-- I don't know how to select preceding text -->
<xsl:template match="/svg/g/g[3]"/>
</stylesheet>

我尝试使用此代码来转换第三个 &lt;g&gt; 标记之后的文本元素:

<xsl:template match="svg:text">
<xsl:choose>
 <xsl:when test="(following::svg:g[3])[parent::svg:g]">
               <xsl:copy-of select="."/>
 </xsl:when>
 <xsl:otherwise/>
 </xsl:choose>
</xsl:template>

...那没有用。

【问题讨论】:

  • 请花点时间亲自尝试一下并分享您的样式表。如果您曾经针对 XSLT 处理器运行过输入 XML,您就会知道它的格式不正确。
  • @Mathias 我已经运行了它,但忘记包含我的 xslt 代码。我编辑了上面的代码以取出敏感数据。

标签: xml xslt xpath svg


【解决方案1】:

目前尚不清楚该解决方案应该具有多少通用性,您可以按照非常简单的样式表使用

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" exclude-result-prefixes="xlink">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

    <xsl:template match="/">
        <svg>
            <xsl:apply-templates select="svg:svg/svg:g" />
        </svg>
    </xsl:template>

    <xsl:template match="svg:svg/svg:g">
        <g>
            <xsl:copy-of select="svg:g[1]" />
            <xsl:copy-of select="svg:text[3]" />
        </g>
    </xsl:template>

</xsl:stylesheet>

【讨论】:

  • +1 是一个简单而好的解决方案。只是一个小问题:xmlns:xlink="http://www.w3.org/1999/xlink" 被添加到输出元素中。
  • @JirkaŠ。 svg:svg/svg:g 具体是做什么的?我在网上到处都看过,但我无法理解 : 在 XSLT 中的作用
  • 在根元素中有命名空间http://www.w3.org/2000/svg 的定义,这与前缀“svg”(某种缩写)相关联。 svg:svg 表示来自命名空间http://www.w3.org/2000/svg 的元素“svg”,svg:g 表示来自命名空间http://www.w3.org/2000/svg...的元素“g”(查看en.wikipedia.org/wiki/XML_namespace)。而“svg:svg/svg:g”表示元素“g”与父元素“svg”。
【解决方案2】:

对于内部g元素的选择,可以依赖position()函数。对于text元素,只需检查是否有以下兄弟。

另外,请注意,必须使用 SVG 命名空间限定元素。

样式表

<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:svg="http://www.w3.org/2000/svg">

<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:template match="/">
  <xsl:apply-templates/>
</xsl:template>

<xsl:template match="svg:svg|svg:g[parent::svg:svg]">
  <xsl:copy>
     <xsl:apply-templates/>
  </xsl:copy>
</xsl:template>

<!-- Match all g elements that are desendents of a g element -->  
<xsl:template match="svg:g[parent::svg:g]">
  <xsl:choose>
     <xsl:when test="position() = 1">
        <xsl:copy>
           <xsl:copy-of select="*|@*"/>
        </xsl:copy>
     </xsl:when>
     <xsl:otherwise/>
  </xsl:choose>
</xsl:template>

<xsl:template match="svg:text">
  <xsl:choose>
     <xsl:when test="not(following-sibling::*)">
        <xsl:copy>
           <xsl:value-of select="."/>
        </xsl:copy>
     </xsl:when>
     <xsl:otherwise/>
  </xsl:choose>
</xsl:template>

</xsl:stylesheet>

输出

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
 <g>
   <g>
       <defs>
             <rect/>
       </defs>
       <clipPath/>
       <polygon/>
   </g>
  <text>Keep this text</text>
 </g>
</svg>

【讨论】:

  • 我什至无法运行您的 XSLT 代码:我收到错误 Error:XSLTProcessor::transformToXml() [&lt;a href='xsltprocessor.transformtoxml'&gt;xsltprocessor.transformtoxml&lt;/a&gt;]: No stylesheet associated to this object
  • 我通过将 xsl: 添加到关闭样式表标记来修复它。 @mathias 您的代码只选择最后一个文本标签,而不是所有跟在第三个内部 &lt;g&gt; 标签之后的文本标签
  • 我尝试使用:
  • 据我所知,我的代码完全符合您在问题中所说的内容。您是否同时编辑了问题?上次查看时,预期输出中只有 1 个“保留此文本”。
  • 任何一般元素或任何text元素?
猜你喜欢
  • 1970-01-01
  • 2020-08-07
  • 1970-01-01
  • 2010-12-26
  • 1970-01-01
  • 1970-01-01
  • 2019-08-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多