XSLT处理混合内容中的空格

时间:2014-03-01 20:54:19

标签: xml xslt whitespace

我遇到空白问题。当我在lb break="no"中有span type="inter"时,单词部分之间会有一个不需要的空格:

<lb n="4" break="no"/>... die Aufmunterung durch das <span type="inter" xml:id="GR55024-inter5">güti
<lb n="5" break="no"/>ge</span>

HTML:

<p>... die Aufmunterung durch das <span class="inter" title="inter5">güti ge</span> ...</p>

在其他情况下,单词部分之间没有空格。

如何将此案例考虑在内?我有一个相当复杂的样式表,它应该输出一个带连字符的单词,并且不应该删除p中的任何空白节点。我知道解决这个问题可能不是一个非常优雅的方法,但我希望你能帮助我。

这是一个xml:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-model href="http://www.tei-c.org/release/xml/tei/custom/schema/relaxng/tei_all.rng" type="application/xml" schematypens="http://relaxng.org/ns/structure/1.0"?>
<?xml-model href="http://www.tei-c.org/release/xml/tei/custom/schema/relaxng/tei_all.rng" type="application/xml"
schematypens="http://purl.oclc.org/dsdl/schematron"?>
<TEI xmlns="http://www.tei-c.org/ns/1.0">
 <teiHeader>
  <fileDesc>
     <titleStmt>
        <title>Title</title>
     </titleStmt>
     <publicationStmt>
        <p>Publication Information</p>
     </publicationStmt>
     <sourceDesc>
        <p>Information about the source</p>
     </sourceDesc>
  </fileDesc>
 </teiHeader>
  <text>
   <body>
    <div type="header"/>

    <div type="adresse" rend="lateinisch"/>

       <div type="arbeitsphase" n="1" ana="ausfertigung" rend="lateinisch">
          <pb n="1"/>
          <space unit="lines" quantity="5"></space>
          <p>
             <lb n="3"/>Ich ergreife diese Gelegenheit<span type="inter" xml:id="GR55024-inter2">&#32;&#32;</span> eine Bitte an Sie zu rich 
             <lb n="4" break="no"/>ten<span type="inter" xml:id="GR55024-inter3">,</span> zu der Sie mir<span type="inter" xml:id="GR55024-inter4">&#32;&#32;</span> die Aufmunterung durch das <span type="inter" xml:id="GR55024-inter5">güti
             <lb n="5" break="no"/>ge</span> Versprechen gaben, <span type="inter" xml:id="GR55024-inter6">im Fall</span> ich Bücher von der <span type="inter" xml:id="GR55024-inter7">Je 
             <lb n="6" break="no"/>naischen</span> Bibliothek<ptr type="app" target="#GR55024-seite1-les1"/> <span type="inter" xml:id="GR55024-inter8">nöthig haben sollte,</span> mir dieselben 
             <lb n="7"/><span type="inter" xml:id="GR55024-inter9">gefälligst</span> zu verschaffen. Ich <span type="inter" xml:id="GR55024-inter10">bedarf</span> jetzt zur Recen 
             <lb n="8" break="no"/>sion des <span type="inter" xml:id="GR55024-inter11">Buches</span> über <span type="inter" xml:id="GR55024-inter12">die Verwandschaft</span> der <span type="inter" xml:id="GR55024-inter13">griechischen 
             <lb n="9"/>und deutschen</span> Sprache<span type="inter" xml:id="GR55024-inter14">&#32;&#32;</span> <span type="inter" xml:id="GR55024-inter15">das <title type="werk" key=""><hi rend="unterstrichen">Glossarium von <persName key="">Hesychius</persName></hi>, 
             <lb n="10"/>edit. Alberti &#x26; Ruhnkenii</title>,</span> <span type="inter" xml:id="GR55024-inter16">und</span> <title type="werk" key=""><hi rend="unterstrichen"><persName key="">Gregorius Corinthius</persName></hi>
             <lb n="11"/>de dialectis</title>, in der holländ. Ausgabe von <hi rend="unterstrichen"><persName key="">Koen</persName></hi>, <hi rend="unterstrichen">in 8º</hi> und 
        </p>
   </div>
 </body>
 <back>
    <div type="apparat">
       <listApp>
          <app xml:id="GR55024-seite1-les1">
             <rdg>Bibliothe<subst><del rend="durchgestrichenes">c</del></subst>k</rdg>
          </app>
       </listApp> 
    </div>
    </back>  
   </text>
 </TEI>

这是一个xslt样式表:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:tei="http://www.tei-c.org/ns/1.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs tei" version="1.0">
<xsl:output omit-xml-declaration="yes" indent="no" encoding="ISO-8859-1"/>
<xsl:template match="tei:teiHeader"/>
<xsl:template match="tei:div[@type='apparat']"/>
<xsl:template match="tei:body">
 <html>
 <head>
   <style type="text/css">
    .unterstrichen{
    text-decoration:underline;}
    .inter{
    background:yellow;}
   </style>
 </head>
 <body>
 <div id="ausfertigung" class="edierter-text">
                    <center><h4>Edierter Text</h4></center>
                    <div class="arbeitsphase-{//tei:div[@type='arbeitsphase']/@n}">
                        <xsl:apply-templates select="//tei:div[@type='arbeitsphase']"/>
                    </div>
                </div>
 </body>
 </html>
</xsl:template>
<xsl:template match="tei:ptr[@type='kom']">
    <xsl:variable name="kommentarID" select="substring-after(@target, '#')"/>
    <span class="noteLink" onclick="" id="{$kommentarID}">[<xsl:number count="tei:ptr[@type='kom']"></xsl:number>]
    </span>
</xsl:template>
<xsl:template match="tei:div[@type='kommentar']//tei:note">
    <span class="note" id="{ attribute::xml:id}">
        <span class="noteNumber">[<xsl:number count="tei:div[@type='kommentar']//tei:note"></xsl:number>]</span>
        <xsl:apply-templates select="tei:p"/>
    </span>
</xsl:template>
<xsl:template match="tei:pb">
   <xsl:variable name="n" select="concat('Seite', '-', @n)"/>
   <xsl:variable name="facs" select="substring-before(@facs, '.jpg')"/>
   <div class="bild-icon" id="{$n}">
       <a id="{facs}" class="popup-closed" href="#"><img src="facs-icon.jpg" alt=""/><span class="pb-num"><xsl:text>Seite </xsl:text><xsl:value-of select="@n"></xsl:value-of></span>
           <xsl:apply-templates></xsl:apply-templates>
       </a>
   </div>
</xsl:template>
<xsl:template match="tei:ptr[@type='app']">
    <xsl:variable name="kommentarID" select="substring-after(@target, '#')"/>
    <span class="tip">
        <a tabindex="1">
            <em>*</em>
        </a>
        <span class="answer" id="{$kommentarID}">
            <xsl:apply-templates select="//tei:app[@xml:id = $kommentarID]"/>
        </span>
    </span>
</xsl:template>
<xsl:template match="tei:span[@type='inter']">
    <xsl:variable name="kommentarID" select="substring-after(@xml:id, '-')"/>
    <xsl:choose>
        <xsl:when test="@ana='leer'">
            <span class="inter" title="{$kommentarID}" style="width:1em;">
                <xsl:apply-templates/>
            </span>
        </xsl:when>
        <xsl:otherwise>
            <span class="inter" title="{$kommentarID}">
        <xsl:apply-templates/>
    </span>
        </xsl:otherwise>
    </xsl:choose>
 </xsl:template>
 <xsl:template match="tei:del">
    <xsl:choose>
        <xsl:when test="@rend='überschriebenes'">
            <span class="überschriebenes">
                <xsl:apply-templates/>
            </span>
        </xsl:when>
    </xsl:choose>
    <xsl:choose>
        <xsl:when test="@rend='durchgestrichenes'">
            <span class="durchgestrichenes">
                <xsl:apply-templates/>
            </span>
        </xsl:when>
    </xsl:choose>
    <xsl:choose>
        <xsl:when test="@rend='nicht_durchgestrichenes'">
            <span class="nicht_durchgestrichenes">
                <xsl:apply-templates/>
            </span>
        </xsl:when>
    </xsl:choose>
    <xsl:choose>
        <xsl:when test="@rend='spätere_streichung'">
            <span class="spätere_streichung">
                <xsl:apply-templates/>
            </span>
        </xsl:when>
    </xsl:choose>
</xsl:template>
<xsl:template match="tei:add">
    <xsl:choose>
        <xsl:when test="@place='über_Zeile'"><xsl:text disable-output-escaping="yes">&amp;#8968;</xsl:text><span class="über_Zeile">
                <xsl:apply-templates/>
            </span><xsl:text disable-output-escaping="yes">&amp;#8969; </xsl:text></xsl:when>
    </xsl:choose>
    <xsl:choose>
        <xsl:when test="@place='unter_Zeile'"><xsl:text disable-output-escaping="yes">&amp;#8970;</xsl:text><span class="unter_Zeile">
                <xsl:apply-templates/>
            </span><xsl:text disable-output-escaping="yes">&amp;#8971; </xsl:text></xsl:when>
    </xsl:choose>
    <xsl:choose>
        <xsl:when test="@place='in_Zeile'"><xsl:text disable-output-escaping="yes">&amp;#9474;</xsl:text><span class="in_Zeile">
                <xsl:apply-templates/>
            </span><xsl:text disable-output-escaping="yes">&amp;#9474; </xsl:text></xsl:when>
    </xsl:choose>
    <xsl:choose>
        <xsl:when test="@place='Rand_rechts'"><xsl:text disable-output-escaping="yes">&amp;#8968;</xsl:text><span class="Rand_rechts">
                <xsl:apply-templates/>
            </span><xsl:text disable-output-escaping="yes">&amp;#8968;</xsl:text></xsl:when>
    </xsl:choose>
    <xsl:choose>
        <xsl:when test="@place='Rand_links'"><xsl:text disable-output-escaping="yes">&amp;#8969;</xsl:text><span class="Rand_links">
                <xsl:apply-templates/>
            </span><xsl:text disable-output-escaping="yes">&amp;#8969; </xsl:text></xsl:when>
    </xsl:choose>
    <xsl:choose>
        <xsl:when test="@place='Rand_unten'"><xsl:text disable-output-escaping="yes">&amp;#8595;</xsl:text><span class="Rand_unten">
                <xsl:apply-templates/>
            </span><xsl:text disable-output-escaping="yes">&amp;#8595; </xsl:text></xsl:when>
    </xsl:choose>
    <xsl:choose>
        <xsl:when test="@place='Rand_oben'"><xsl:text disable-output-escaping="yes">&amp;#8593;</xsl:text><span class="Rand_oben">
                <xsl:apply-templates/>
            </span><xsl:text disable-output-escaping="yes">&amp;#8593; </xsl:text></xsl:when>
    </xsl:choose>
    <xsl:choose>
        <xsl:when test="@place='rechte_Spalte'"><xsl:text disable-output-escaping="yes">&amp;#8968;</xsl:text><span class="rechte_Spalte">
                <xsl:apply-templates/>
            </span><xsl:text disable-output-escaping="yes">&amp;#8968; </xsl:text></xsl:when>
    </xsl:choose>
    <xsl:choose>
        <xsl:when test="@place='linke_Spalte'"><xsl:text disable-output-escaping="yes">&amp;#8969;</xsl:text><span class="linke_Spalte">
                <xsl:apply-templates/>
            </span><xsl:text disable-output-escaping="yes">&amp;#8969; </xsl:text></xsl:when>
    </xsl:choose>
    <xsl:choose>
        <xsl:when test="@rend='überschreibung'">
            <span class="überschreibung">
                <xsl:apply-templates/>
            </span>
        </xsl:when>
    </xsl:choose>
 </xsl:template>
 <xsl:template match="tei:ex[@type='editor']">
    <span class="editor" style="font-style:italic; font-size:70%;">
        <xsl:apply-templates/>
    </span>
 </xsl:template>
 <!--Templates, die Trennstriche l¿schen und Anzahl der Whitespaces im Text nicht ¿ndern!-->
 <!-- Match if the preceding node (not necessarily sibling) that is either
  a non-empty-space-text node or an <lb> is an <lb break='no'> -->
 <xsl:template
    match="text()[
    (preceding::node()[
    self::text()[normalize-space() != ''] or
    self::tei:lb])
    [last()]
    [self::tei:lb[@break='no']]
    ]">
    <!-- Trim whitespace on the left. Thanks to Alejandro,
        http://stackoverflow.com/a/3997107/423105 -->
    <xsl:variable name="firstNonSpace" select="substring(normalize-space(), 1, 1)"/>
    <xsl:value-of
        select="concat($firstNonSpace,
        substring-after(., $firstNonSpace))"/>
    </xsl:template>
    <!-- Match if the next node (not necessarily sibling) that is either
  a non-empty-space-text node or an <lb> is an <lb break='no'> -->
    <xsl:template
    match="text()[
    following::node()[
    self::text()[normalize-space() != ''] or
    self::tei:lb]
    [1]
    [self::tei:lb[@break='no']]
    ]">
    <xsl:variable name="normalized" select="normalize-space()"/>
    <xsl:if test="$normalized != ''">
        <xsl:variable name="lastNonSpace"
            select="substring($normalized, string-length($normalized))"/>
        <xsl:variable name="trimmedSuffix">
            <xsl:call-template name="substring-after-last">
                <xsl:with-param name="string" select="."/>
                <xsl:with-param name="delimiter" select="$lastNonSpace"/>
            </xsl:call-template>
        </xsl:variable>
        <xsl:value-of
            select="substring(., 1, string-length(.) -
            string-length($trimmedSuffix))"
        />
    </xsl:if>
    <!-- otherwise output nothing. -->
    </xsl:template>


   <!-- Thanks to Jeni Tennison:
    http://www.stylusstudio.com/xsllist/200111/post00460.html -->
   <xsl:template name="substring-after-last">
    <xsl:param name="string"/>
    <xsl:param name="delimiter"/>
    <xsl:choose>
        <xsl:when test="contains($string, $delimiter)">
            <xsl:call-template name="substring-after-last">
                <xsl:with-param name="string" select="substring-after($string, $delimiter)"/>
                <xsl:with-param name="delimiter" select="$delimiter"/>
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="$string"/>
        </xsl:otherwise>
    </xsl:choose>
   </xsl:template>
  <xsl:template priority=".7" match="text()[position()=1 and not((ancestor::node()/@xml:space)[position()=last()]='preserve')]">
    <xsl:value-of select="normalize-space()"/>
    <xsl:if test="normalize-space(substring(., string-length(.))) = ''">
        <xsl:text> </xsl:text>
    </xsl:if>
   </xsl:template>
  <xsl:template match="tei:p">
    <p>
        <xsl:apply-templates/>
    </p>
  </xsl:template>
  <xsl:template match="tei:emph[@rend='lateinisch']">
    <span class="lateinisch" style="font-family: Arial; font-size:90%">
        <xsl:apply-templates/>
    </span>
  </xsl:template>
  <xsl:template match="tei:space">
    <xsl:choose>
        <xsl:when test="@unit='chars'">
            <span style="display:inline-block;width: {@quantity div 2}em;">&#160;
                <xsl:apply-templates/>
            </span>
        </xsl:when>
    </xsl:choose>
    <xsl:choose>
        <xsl:when test="@unit='lines'"> &#160;<span style="height:{@quantity}ex; display:block;"
                >&#160; <xsl:apply-templates/>
            </span>
        </xsl:when>
    </xsl:choose>
    </xsl:template>
    <xsl:template match="tei:hi">
    <xsl:choose>
        <xsl:when test="@ana='rot' and  not(@rend)">
            <span class="rot" style="color:#B40404">
                <xsl:apply-templates/>
            </span>
        </xsl:when>
        <xsl:when test="@ana='rot' and @rend='unterstrichen'">
            <span class="rot_unter" style="border-bottom: solid #B40404 1px;">
                <xsl:apply-templates/>
            </span>
        </xsl:when>
        <xsl:when test="@ana='schwarz'">
            <span class="schwarz" style="color:#000000">
                <xsl:apply-templates/>
            </span>
        </xsl:when>
        <xsl:otherwise>
            <span class="{@rend}">
                <xsl:apply-templates/>
            </span>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

我得到的输出:

  <html>
   <head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
    <style type="text/css">
 .unterstrichen{
 text-decoration:underline;}
 .inter{
 background:yellow;}
   </style>
  </head>
  <body>
   <div id="ausfertigung" class="edierter-text">
    <center><h4>Edierter Text</h4></center>
      <div class="arbeitsphase-1">
        <div class="bild-icon" id="Seite-1"><a id="" class="popup-closed" href="#"><img src="facs-icon.jpg" alt=""><span class="pb-num">Seite 1</span></a></div>
           &nbsp;<span style="height:5ex; display:block;">&nbsp; </span>
          <p> Ich ergreife diese Gelegenheit<span class="inter" title="inter2"> </span> eine Bitte an Sie zu richten<span class="inter" title="inter3">,</span> zu der Sie mir<span class="inter" title="inter4"> </span> die Aufmunterung durch das <span class="inter" title="inter5">güti ge</span> Versprechen gaben, <span class="inter" title="inter6">im Fall</span> ich Bücher von der <span class="inter" title="inter7">Je naischen</span> Bibliothek<span class="tip"><a tabindex="1"><em>*</em></a><span class="answer" id="GR55024-seite1-les1"> Bibliothe<span class="durchgestrichenes">c</span>k
          </span></span> <span class="inter" title="inter8">nöthig haben sollte,</span> mir dieselben 
             <span class="inter" title="inter9">gefälligst</span> zu verschaffen. Ich <span class="inter" title="inter10">bedarf</span> jetzt zur Recension des <span class="inter" title="inter11">Buches</span> über <span class="inter" title="inter12">die Verwandschaft</span> der <span class="inter" title="inter13">griechischen und deutschen</span> Sprache<span class="inter" title="inter14"> </span> <span class="inter" title="inter15">das <span class="unterstrichen">Glossarium von Hesychius</span>, edit. Alberti &amp; Ruhnkenii,</span> <span class="inter" title="inter16">und</span> <span class="unterstrichen">Gregorius Corinthius</span> de dialectis, in der holländ. Ausgabe von <span class="unterstrichen">Koen</span>, <span class="unterstrichen">in 8º</span> und 
        </p>
   </div>
  </div>
 </body>
 </html>

我正在使用Oxygen Xml Editor和Saxon HE 9.4.0.6处理器。

1 个答案:

答案 0 :(得分:1)

此模板:

<xsl:template priority=".7" match="text()[position()=1 and not((ancestor::node()/@xml:space)[position()=last()]='preserve')]">
    <xsl:value-of select="normalize-space()"/>
    <xsl:if test="normalize-space(substring(., string-length(.))) = ''">
        <xsl:text> </xsl:text>
    </xsl:if>
</xsl:template>

导致你的空白,因为它在<span> text()position()=1匹配[not(parent::tei:span)]不确定是否真的需要这样做,删除模板会得到正确的输出。

如果仍然需要,可以通过将{{1}}添加到模板匹配中,将其从span中的文本中排除。