2016-09-15 12 views
1

Я хочу извлечь короткие тексты из текста для некоторых пояснительных примечаний. То есть, если текст слишком длинный, он должен выводить только первое и последнее слово. Это работает:Аббревиатура текста пробелом с XSLT

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

<lemma> 
    <a><b>I</b> can what I can and <b><c>what</c></b> I can't I can</a> 
</lemma> 

когда XSLT применяется

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       xmlns:xs="http://www.w3.org/2001/XMLSchema" 
       version="2.0"> 

    <xsl:output method="xml" encoding="utf-8" indent="yes"/> 

    <!-- Identity template : copy all text nodes, elements and attributes --> 
    <xsl:template match="@*|node()"> 
     <xsl:copy copy-namespaces="no"> 
     <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 

<xsl:template match="lemma"> 
    <xsl:value-of select="."/> 
    <xsl:choose> 
     <xsl:when test="string-length(normalize-space(a)) > 20"> 
     <xsl:value-of select="tokenize(a,' ')[1]"/> 
     <xsl:text> […] </xsl:text> 
     <xsl:value-of select="tokenize(a,' ')[last()]"/> 
     </xsl:when> 
     <xsl:otherwise> 
     <xsl:value-of select="a"/> 
     </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

</xsl:stylesheet> 

производит желаемый результат:

я могу, что я могу и чего не могу я могу

I [...] can

К сожалению, когда два дочерних элемента сразу смежны, пространство между ними кодируется как дочерний узел с именем «пробел». Выше решение не работает с:

<lemma> 
    <a><b>I</b><space/><b>can</b> what I can and what I can't I can</a> 
</lemma> 

Я пытался иметь единое пространство-специальный символ обрабатывается раньше, но это не работает (и я знаю, почему), я просто не знаю, как делать это лучше. Полагаю, он будет работать с двумя XLST-прогонами.

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       xmlns:xs="http://www.w3.org/2001/XMLSchema" 
       version="2.0"> 

    <xsl:output method="xml" encoding="utf-8" indent="yes"/> 

    <!-- Identity template : copy all text nodes, elements and attributes --> 
    <xsl:template match="@*|node()"> 
     <xsl:copy copy-namespaces="no"> 
     <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 

<xsl:template match="space"> 
     &#160; 
</xsl:template> 

<xsl:template match="lemma"> 
    <xsl:apply-templates select="space"/> 
    <xsl:value-of select="."/> 
    <xsl:choose> 
     <xsl:when test="string-length(normalize-space(a)) > 20"> 
     <xsl:value-of select="tokenize(a,' ')[1]"/> 
     <xsl:text> […] </xsl:text> 
     <xsl:value-of select="tokenize(a,' ')[last()]"/> 
     </xsl:when> 
     <xsl:otherwise> 
     <xsl:value-of select="a"/> 
     </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

</xsl:stylesheet> 

Выход:

Ican, что я могу и чего не могу я

Ican [...] может

ответ

1

Вы можете сделать xsl:apply-templates обрабатывать a и сохранить его в переменной ...

XML Input

<doc> 
    <lemma> 
     <a><b>I</b> can what I can and <b><c>what</c></b> I can't I can</a> 
    </lemma> 
    <lemma> 
     <a><b>I</b><space/><b>can</b> what I can and what I can't I can</a> 
    </lemma> 
</doc> 

XSLT 2,0

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output indent="yes"/> 
    <xsl:strip-space elements="*"/> 

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

    <xsl:template match="space"> 
    <xsl:text> </xsl:text> 
    </xsl:template> 

    <xsl:template match="lemma"> 
    <xsl:variable name="a"> 
     <xsl:apply-templates select="a"/> 
    </xsl:variable> 
    <xsl:variable name="norm" select="normalize-space($a)"/> 
    <xsl:variable name="tokens" select="tokenize($norm,'\s')"/> 
    <xsl:copy> 
     <result> 
     <xsl:value-of select="$norm"/> 
     </result> 
     <result> 
     <xsl:value-of select=" 
      if (string-length($norm) > 20) then 
      concat($tokens[1],' […] ', $tokens[last()]) 
      else $norm"/> 
     </result> 
    </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

XML Output

<doc> 
    <lemma> 
     <result>I can what I can and what I can't I can</result> 
     <result>I […] can</result> 
    </lemma> 
    <lemma> 
     <result>I can what I can and what I can't I can</result> 
     <result>I […] can</result> 
    </lemma> 
</doc>