XSLT-токенизация строки, которая распределена по дочерним элементам - PullRequest
1 голос
/ 18 марта 2012

У меня такое ощущение, что есть очевидное решение, но я не могу об этом думать.Используя XSLT 2.0, я хочу маркировать строку, которая распределена по дочерним элементам, так что это что-то вроде

<line>
    <font style="big">
        <text color="blue">wha</text>
    </font>
    <font style="small">
        <text color="red">t is o</text>
    </font>
    <font style="small">
        <text color="blue">n </text>
    </font>
    <font style="small">
        <text color="blue">his </text>
    </font>
    <font style="small">
        <text color="blue">mind.</text>
    </font>
</line>

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

<line>
    <token>
        <font style="big">
            <text color="blue">wha</text>
        </font>
        <font style="small">
            <text color="red">t</text>
        </font>
    </token>
    <token>
        <font style="small">
            <text color="red">is</text>
        </font>
    </token>
    <token>
        <font style="small">
            <text color="red">o</text>
        </font>
        <font style="small">
            <text color="blue">n</text>
        </font>
    </token>
  <token>
      <font style="small">
          <text color="blue">his</text>
      </font>
  </token>
  <token>
    <font style="small">
        <text color="blue">mind</text>
    </font>
  </token>
  <token>
    <font style="small">
      <text color="blue">.</text>
    </font>
  </token
</line>

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

Я буду рад услышать ваши идеи, Рупрехт

1 Ответ

2 голосов
/ 18 марта 2012

Это выполняет половину работы, разбивая строки на строки, но не добавляет вашу разметку <token>, как будто я правильно понимаю, что для поиска слов требуется поиск по словарю.Он создает

<line>
   <font style="big">
      <text color="blue">wha</text>
   </font>
   <font style="small">
      <text color="red">t</text>
   </font>
   <font style="small">
      <text color="red">is</text>
   </font>
   <font style="small">
      <text color="red">o</text>
   </font>
   <font style="small">
      <text color="blue">n</text>
   </font>
   <font style="small">
      <text color="blue">his</text>
   </font>
   <font style="small">
      <text color="blue">mind.</text>
   </font>
</line>

таблицу стилей:

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

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

<xsl:template match="*">
 <xsl:copy>
  <xsl:copy-of select="@*"/>
  <xsl:apply-templates/>
 </xsl:copy>
</xsl:template>

<xsl:template match="font">
 <xsl:variable name="fa" select="@*"/>
 <xsl:for-each select="text">
  <xsl:variable name="ta" select="@*"/>
  <xsl:for-each select="text()/tokenize(.,'\s+')[.]">
   <font>
    <xsl:copy-of select="$fa"/>
    <text>
     <xsl:copy-of select="$ta"/>
     <xsl:value-of select="."/>
    </text>
   </font>
  </xsl:for-each>
 </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

ОК, обновленный после уточнения в комментариях, теперь он генерирует

<line>
   <token>
      <font style="big">
         <text color="blue">wha</text>
      </font>
      <font style="small">
         <text color="red">t</text>
      </font>
   </token>
   <token>
      <font style="small">
         <text color="red">is</text>
      </font>
   </token>
   <token>
      <font style="small">
         <text color="red">o</text>
      </font>
      <font style="small">
         <text color="blue">n</text>
      </font>
   </token>
   <token>
      <font style="small">
         <text color="blue">his</text>
      </font>
   </token>
   <token>
      <font style="small">
         <text color="blue">mind</text>
      </font>
   </token>
   <token>
      <font style="small">
         <text color="blue">.</text>
      </font>
   </token>
</line>

xslt:

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

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

 <xsl:template match="*">
  <xsl:copy>
   <xsl:copy-of select="@*"/>
   <xsl:apply-templates/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="*[font]">
  <xsl:copy>
   <xsl:copy-of select="@*"/>
   <xsl:variable name="p1">
    <xsl:apply-templates/>
   </xsl:variable>
   <xsl:for-each-group  select="$p1/*" group-starting-with="tok">
    <token>
     <xsl:copy-of select="current-group() except self::tok"/>
    </token>
   </xsl:for-each-group>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="font">
  <xsl:variable name="fa" select="@*"/>
  <xsl:for-each select="text">
   <xsl:variable name="ta" select="@*"/>
   <xsl:if test="position()=1 and matches(.,'^\s')"><tok/></xsl:if>
   <xsl:for-each select="text()/tokenize(.,'\s+')[.]">
    <xsl:if test="position()!=1"><tok/></xsl:if>
    <xsl:analyze-string regex="[.,;?]" select=".">
     <xsl:matching-substring>
      <tok/>
      <font>
       <xsl:copy-of select="$fa"/>
       <text>
    <xsl:copy-of select="$ta"/>
    <xsl:value-of select="."/>
       </text>
      </font>
     </xsl:matching-substring>
     <xsl:non-matching-substring>
      <font>
       <xsl:copy-of select="$fa"/>
       <text>
    <xsl:copy-of select="$ta"/>
    <xsl:value-of select="."/>
       </text>
      </font>
     </xsl:non-matching-substring>
    </xsl:analyze-string>
   </xsl:for-each>
   <xsl:if test="position()=last() and matches(.,'\s$')"><tok/></xsl:if>
  </xsl:for-each>
 </xsl:template>

</xsl:stylesheet>
...