使用字符串长度条件将XSLT中的XML转换为HTML [英] Transform XML to HTML in XSLT with string length condition

查看:90
本文介绍了使用字符串长度条件将XSLT中的XML转换为HTML的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用TEI构建的XML文件,如下所示:

 < div type =chaptern =1 > 
< p>
< s xml:id =f_1>句子f1< / s>
< / p>
< p>
< s xml:id =e_2>句子e2< / s>
< / p>
< / div>

< div type =chaptern =2>
<! - - >
< / div>

我需要将其转换为以下HTML结构:

 < div> 
< h1>第1章< / h1>
< div class =book-content>
< p>
< span class ='source-language-sent'data-source-id ='1'>句子e1。< / span>
< span id ='1'style ='display:none'> sentence f1< / span>
< / p>
< p>
< span class ='source-language-sent'data-source-id ='2'>句子e2< / span>
< span id ='2'style ='display:none'> sentence f2< / span>
< / p>
< / div>
< / div>
< div>
< h1>第2章< / h1>
< div class =book-content>
<! - - >
< / div>
< / div>

现在我使用这个XSLT文件:

 <?xml version =1.0encoding =UTF-8?> 
< xsl:output method =htmlencoding =UTF-8indent =yes/>

< xsl:template match =tei:body>
< xsl:apply-templates />
< / xsl:template>

< xsl:template match =tei:teiHeader>
< xsl:comment>
< xsl:apply-templates select =node()/>
< / xsl:comment>
< / xsl:template>

<! - - 创建章节 - >
< xsl:template match =tei:div>
< xsl:element name =div>
< xsl:element name =div>
< xsl:attribute name =class>
< xsl:text> book-content< / xsl:text>
< / xsl:attribute>
< xsl:element name =h1>
< xsl:text>章< / xsl:text>
< xsl:value-of select =@ n/>
< / xsl:element>
< xsl:apply-templates select =node()/>
< / xsl:element>
< / xsl:element>
< / xsl:template>

<! - create p - >
< xsl:template match =tei:p>
< xsl:element name =p>
< xsl:apply-templates />
< / xsl:element>
< / xsl:template>

<! - create s - >
< xsl:template match =tei:s>
< xsl:if test =starts-with($ xmlid,'e')>
< xsl:element name =span>
< xsl:attribute name =class>
< xsl:text>源语言发送< / xsl:text>
< / xsl:attribute>
< xsl:attribute name =data-source-id>
< xsl:value-of select =substring($ xmlid,3,4)/>
< / xsl:attribute>
< xsl:apply-templates select =node()/>
< / xsl:element>
< / xsl:if>
< xsl:if test =starts-with($ xmlid,'f')>
< xsl:element name =span>
< xsl:attribute name =style>
< xsl:text> display:none< / xsl:text>
< / xsl:attribute>
< xsl:attribute name =id>
< xsl:value-of select =substring($ xmlid,3,4)/>
< / xsl:attribute>
< xsl:apply-templates select =node()/>
< / xsl:element>
< / xsl:if>
< / xsl:template>

< / xsl:stylesheet>

我的问题是我需要创建一个新的< div class = book-content> foreach 900个字符。但我不想削减我的 s 元素,所以我需要计算我需要多少个 s 元素包含在一个< div class =book-content> 中,以包含900个字符。 >解决方案

这是一个有趣的问题,但你的例子有太多的其他事情发生。我喜欢用我自己的例子单独解决这个问题。



考虑以下输入:

XML

 < book> 
< chapter id =A>
< para>
< sentence id =1length =23>玛丽有一只小羊羔,< / sentence>
<句号id =2length =29>他的羊毛像白雪一样白,< / sentence>
< sentence id =3length =30>玛丽去过的地方,< / sentence>
< / para>
< para>
< sentence id =4length =24>羊肉一定要去。< / sentence>
< sentence id =5length =34>他一天跟着她上学,< / sentence>
< / para>
< para>
<句子id =6length =27>违反规则,< / sentence>
< sentence id =7length =35>它让孩子们笑起来玩< / sentence>
< sentence id =8length =24>在学校看到一只羊。< / sentence>
< / para>
< para>
< sentence id =9length =34>所以老师把它翻出来了,< / sentence>
<句子id =10length =27>但它仍然徘徊在附近。< / sentence>
< / para>
< / chapter>
< chapter id =B>
< para>
<句子id =11length =35>夏令时,livin'很容易。< / sentence>
<句子id =12length =40>鱼正在跳跃,而棉花也很高。< / sentence>
<句子id =13length =52>哦,你爸爸的富有和你妈妈的好lookin'。< / sentence>
<句子id =14length =35>所以嘘小宝贝,不要哭泣。< / sentence>
< sentence id =15length =54>这些早晨的其中一个,你会唱起歌来。< / sentence>
< / para>
< para>
<句子id =16length =57>然后你就会展开你的翅膀,你就会翱翔天空。< / sentence>
< sentence id =17length =35>所以嘘小宝宝,不要哭泣。< / sentence>
< / para>
< / chapter>
< / book>

注意长度值仅供参考;我们不会在解决方案中使用它们。



我们的任务是将每个总长度超过200个字符的章节拆分为几章, >整个句子,同时保留句子组之间的原始段落边界。

XSLT 1.0

 < xsl:stylesheet version =1.0
xmlns:xsl =http://www.w3.org/1999/XSL /转换
xmlns:exsl =http://exslt.org/common
xmlns:set =http://exslt.org/sets
扩展元素前缀=exsl set>

<! - 身份转换 - >
< xsl:template match =@ * | node()>
< xsl:copy>
< xsl:apply-templates select =@ * | node()/>
< / xsl:copy>
< / xsl:template>

< xsl:template match =chapter>
< xsl:call-template name =split-chapter>
< xsl:with-param name =nodesselect =para / sentence/>
< / xsl:call-template>
< / xsl:template>

< xsl:template name =split-chapter>
< xsl:param name =nodes/>
< xsl:param name =limitselect =200/>
< xsl:param name =remaining-nodesselect =dummy-node/>
<! - - 1.计算节点的总长度 - >
< xsl:variable name =长度>
< xsl:for-each select =$ nodes>
< length>
< xsl:value-of select =string-length()/>
< /长度>
< / xsl:for-each>
< / xsl:variable>
<! - - 2.处理章节: - >
<! - 如果章节太长并且可以缩短... - >
< xsl:when test =$ total-length> $ limit and count($ nodes)> 1>
<! - ...再次尝试少一个节点。 - >
< xsl:call-template name =split-chapter>
< / xsl:call-template>
< / xsl:when>
< xsl:otherwise>
<! - - 否则用当前节点创建一个章节... - >
<! - - ...列出参与本章的分支... - >
< xsl:for-each select =$ nodes / parent :: para>
< para>
<! - ...并处理每个段落中仍然留下的节点。 - >
< / para>
< / xsl:for-each>
< / chapter>
<! - 然后处理任何剩余的节点。 - >
< xsl:if test =$ remaining-nodes>
< xsl:call-template name =split-chapter>
< xsl:with-param name =nodesselect =$ remaining-nodes/>
< / xsl:call-template>
< / xsl:if>
< / xsl:otherwise>
< / xsl:template>

< / xsl:stylesheet>

结果

 <?xml version =1.0encoding =utf-8?> 
< book>
< chapter id =Alength =167>
< para>
< sentence id =1length =23>玛丽有一只小羊羔,< / sentence>
<句号id =2length =29>他的羊毛像白雪一样白,< / sentence>
< sentence id =3length =30>玛丽去过的地方,< / sentence>
< / para>
< para>
< sentence id =4length =24>羊肉一定要去。< / sentence>
< sentence id =5length =34>他一天跟着她上学,< / sentence>
< / para>
< para>
<句子id =6length =27>违反规则,< / sentence>
< / para>
< / chapter>
< chapter id =Alength =120>
< para>
< sentence id =7length =35>它让孩子们笑起来玩< / sentence>
< sentence id =8length =24>在学校看到一只羊。< / sentence>
< / para>
< para>
< sentence id =9length =34>所以老师把它翻出来了,< / sentence>
<句子id =10length =27>但它仍然徘徊在附近。< / sentence>
< / para>
< / chapter>
< chapter id =Blength =162>
< para>
<句子id =11length =35>夏令时,livin'很容易。< / sentence>
<句子id =12length =40>鱼正在跳跃,而棉花也很高。< / sentence>
<句子id =13length =52>哦,你爸爸的富有和你妈妈的好lookin'。< / sentence>
<句子id =14length =35>所以嘘小宝贝,不要哭泣。< / sentence>
< / para>
< / chapter>
< chapter id =Blength =146>
< para>
< sentence id =15length =54>这些早晨的其中一个,你会唱起歌来。< / sentence>
< / para>
< para>
<句子id =16length =57>然后你就会展开你的翅膀,你就会翱翔天空。< / sentence>
< sentence id =17length =35>所以嘘小宝宝,不要哭泣。< / sentence>
< / para>
< / chapter>
< / book>


I have a XML file using TEI build like that:

<div type="chapter" n="1">
        <p>
          <s xml:id="e_1">sentence e1.</s>
          <s xml:id="f_1">sentence f1</s>
        </p>
        <p>
            <s xml:id="e_2"> sentence e2</s>
            <s xml:id="f_2"> sentence f2</s>
        </p>
</div>

<div type="chapter" n="2">
        <!-- -->
</div>

I need to transform it to this HTML structure:

<div>
<h1>Chapter 1</h1>
<div class="book-content">
 <p>
    <span class='source-language-sent' data-source-id='1'>sentence e1.</span>
    <span id='1' style='display:none'>sentence f1</span>
 </p>
 <p>
    <span class='source-language-sent' data-source-id='2'>sentence e2</span>
    <span id='2' style='display:none'>sentence f2</span>
 </p>
</div>
</div>
<div>
<h1>Chapter 2</h1>
<div class="book-content">
  <!-- -->
</div>
</div>

for now I use this XSLT file:

<?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" version="1.0">
   <xsl:output method="html" encoding="UTF-8" indent="yes" />

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

   <xsl:template match="tei:teiHeader">
      <xsl:comment>
         <xsl:apply-templates select="node()" />
      </xsl:comment>
   </xsl:template>

   <!--create chapter-->
   <xsl:template match="tei:div">
      <xsl:element name="div">
         <xsl:element name="div">
            <xsl:attribute name="class">
               <xsl:text>book-content</xsl:text>
            </xsl:attribute>
            <xsl:element name="h1">
               <xsl:text>Chapter</xsl:text>
               <xsl:value-of select="@n" />
            </xsl:element>
            <xsl:apply-templates select="node()" />
         </xsl:element>
      </xsl:element>
   </xsl:template>

   <!-- create p-->
   <xsl:template match="tei:p">
      <xsl:element name="p">
         <xsl:apply-templates />
      </xsl:element>
   </xsl:template>

   <!-- create s-->
   <xsl:template match="tei:s">
      <xsl:variable name="xmlid" select="@xml:id" />
      <xsl:if test="starts-with($xmlid, 'e')">
         <xsl:element name="span">
            <xsl:attribute name="class">
               <xsl:text>source-language-sent</xsl:text>
            </xsl:attribute>
            <xsl:attribute name="data-source-id">
               <xsl:value-of select="substring($xmlid, 3, 4)" />
            </xsl:attribute>
            <xsl:apply-templates select="node()" />
         </xsl:element>
      </xsl:if>
      <xsl:if test="starts-with($xmlid, 'f')">
         <xsl:element name="span">
            <xsl:attribute name="style">
               <xsl:text>display:none</xsl:text>
            </xsl:attribute>
            <xsl:attribute name="id">
               <xsl:value-of select="substring($xmlid, 3, 4)" />
            </xsl:attribute>
            <xsl:apply-templates select="node()" />
         </xsl:element>
      </xsl:if>
   </xsl:template>

</xsl:stylesheet>

My problem is that I need to create a new <div class="book-content"> foreach 900 characters. But I don't want to cut my s elements so I need to calculate how many selement do I have to include in one <div class="book-content">to have somethings like 900 characters.

解决方案

This is an interesting problem, but your example has too much of other things going on. I prefer to solve this in isolation, using my own example.

Consider the following input:

XML

<book>
    <chapter id="A">
        <para>
            <sentence id="1" length="23">Mary had a little lamb,</sentence>
            <sentence id="2" length="29">His fleece was white as snow,</sentence>
            <sentence id="3" length="30">And everywhere that Mary went,</sentence>
        </para>
        <para>
            <sentence id="4" length="24">The lamb was sure to go.</sentence>
            <sentence id="5" length="34">He followed her to school one day,</sentence>
        </para>
        <para>
            <sentence id="6" length="27">Which was against the rule,</sentence>
            <sentence id="7" length="35">It made the children laugh and play</sentence>
            <sentence id="8" length="24">To see a lamb at school.</sentence>
        </para>
        <para>
            <sentence id="9" length="34">And so the teacher turned it out, </sentence>
            <sentence id="10" length="27">But still it lingered near.</sentence>
        </para>
    </chapter>
    <chapter id="B">
        <para>
            <sentence id="11" length="35">Summertime, and the livin' is easy.</sentence>
            <sentence id="12" length="40">Fish are jumpin' and the cotton is high.</sentence>
            <sentence id="13" length="52">Oh, Your daddy's rich and your mamma's good lookin'.</sentence>
            <sentence id="14" length="35">So hush little baby, don't you cry.</sentence>
            <sentence id="15" length="54">One of these mornings you're going to rise up singing.</sentence>
        </para>
        <para>
            <sentence id="16" length="57">Then you'll spread your wings and you'll take to the sky.</sentence>
            <sentence id="17" length="35">So hush little baby, don't you cry.</sentence>
        </para>
    </chapter>
</book>

Note: the length values are given for illustration only; we will not be using them in the solution.

Our task is to split each chapter whose total length exceeds 200 characters into several chapters, by moving whole sentences only, while preserving the original para boundaries between groups of sentences.

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:exsl="http://exslt.org/common"
xmlns:set="http://exslt.org/sets"
extension-element-prefixes="exsl set">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="*"/>

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

<xsl:template match="chapter">
    <xsl:call-template name="split-chapter">
        <xsl:with-param name="nodes" select="para/sentence"/>
    </xsl:call-template>
</xsl:template>

<xsl:template name="split-chapter">
    <xsl:param name="nodes"/>
    <xsl:param name="limit" select="200"/>
    <xsl:param name="remaining-nodes" select="dummy-node"/>
    <!-- 1. Calculate the total length of nodes -->
    <xsl:variable name="lengths">
        <xsl:for-each select="$nodes">
            <length>
                <xsl:value-of select="string-length()" />
            </length>
        </xsl:for-each>
    </xsl:variable>
    <xsl:variable name="total-length" select="sum(exsl:node-set($lengths)/length)" />
    <!-- 2. Process the chapter: -->
    <xsl:choose>
        <!-- If chapter is too long and can be shortened ... -->
        <xsl:when test="$total-length > $limit and count($nodes) > 1">
            <!-- ... try again with one node less. -->
            <xsl:call-template name="split-chapter">
                <xsl:with-param name="nodes" select="$nodes[not(position()=last())]"/>
                <xsl:with-param name="remaining-nodes" select="$remaining-nodes | $nodes[last()]"/>
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <!-- Otherwise create a chapter with the current nodes ... -->
            <chapter id="{@id}" length="{$total-length}" >
                <!-- ... list the paras participating in this chapter ... -->
                <xsl:for-each select="$nodes/parent::para">
                    <para>
                        <!-- ... and process the nodes still left in each para. -->
                        <xsl:apply-templates select="set:intersection(sentence, $nodes)"/>
                    </para>
                </xsl:for-each>
            </chapter>
            <!-- Then process any remaining nodes. -->
            <xsl:if test="$remaining-nodes">
                <xsl:call-template name="split-chapter">
                    <xsl:with-param name="nodes" select="$remaining-nodes"/>
                </xsl:call-template>
            </xsl:if>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

</xsl:stylesheet>

Result

<?xml version="1.0" encoding="utf-8"?>
<book>
   <chapter id="A" length="167">
      <para>
         <sentence id="1" length="23">Mary had a little lamb,</sentence>
         <sentence id="2" length="29">His fleece was white as snow,</sentence>
         <sentence id="3" length="30">And everywhere that Mary went,</sentence>
      </para>
      <para>
         <sentence id="4" length="24">The lamb was sure to go.</sentence>
         <sentence id="5" length="34">He followed her to school one day,</sentence>
      </para>
      <para>
         <sentence id="6" length="27">Which was against the rule,</sentence>
      </para>
   </chapter>
   <chapter id="A" length="120">
      <para>
         <sentence id="7" length="35">It made the children laugh and play</sentence>
         <sentence id="8" length="24">To see a lamb at school.</sentence>
      </para>
      <para>
         <sentence id="9" length="34">And so the teacher turned it out, </sentence>
         <sentence id="10" length="27">But still it lingered near.</sentence>
      </para>
   </chapter>
   <chapter id="B" length="162">
      <para>
         <sentence id="11" length="35">Summertime, and the livin' is easy.</sentence>
         <sentence id="12" length="40">Fish are jumpin' and the cotton is high.</sentence>
         <sentence id="13" length="52">Oh, Your daddy's rich and your mamma's good lookin'.</sentence>
         <sentence id="14" length="35">So hush little baby, don't you cry.</sentence>
      </para>
   </chapter>
   <chapter id="B" length="146">
      <para>
         <sentence id="15" length="54">One of these mornings you're going to rise up singing.</sentence>
      </para>
      <para>
         <sentence id="16" length="57">Then you'll spread your wings and you'll take to the sky.</sentence>
         <sentence id="17" length="35">So hush little baby, don't you cry.</sentence>
      </para>
   </chapter>
</book>

这篇关于使用字符串长度条件将XSLT中的XML转换为HTML的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆