Динамически сортируйте узлы и размещайте разделители там, где они есть, используя XSLT - PullRequest
0 голосов
/ 02 февраля 2012

У меня есть файл HTML, и я хочу преобразовать в документ XML только с использованием XSLT ..

Я хочу:

  1. Все сохраняемые узлы.
  2. И все элементы отсортированы.
  3. И код должен быть динамически.
  4. У меня есть запятая (,) между элементами, поэтому мне нужно обрабатывать ее как разделитель, такой как <dl>,</dl>, где он находится .. (не только запятая, некоторые части также хотят сохранить)

У меня огромный файл, поэтому я хочу, чтобы простой код обрабатывал все html-узлы. Здесь я объяснил кодирование с помощью xslt если ты понимаешь это, пожалуйста, помогите мне ..

Мой HTML-файл ..

<span id="2102" class="one_biblio">
<span id="2103" class="one_section-title"><b>Title</b></span>
<span id="2204" class="one_authors">
    <span id="2205" class="one_author">, <!--here the comma arraives-->

        <!-- here the id value misplaced -->
        <span id="2207" class="one_surname">Surname</span>,<!--here the comma arraives-->
        <span id="2206" class="one_given-name">GivenName</span>,<!--here the comma arraives-->
  </span>
</span>
<span id="2208" class="one_title">
    <span id="2209" class="one_maintitle">technology</span>
</span>

И я хочу, чтобы выходной XML-файл был: Здесь в качестве имени элемента используется значение класса атрибута. И элементы должны быть отсортированы. И запятая (,) должна быть в теге разделителя.

  <biblio id="2102" >
    <section-title id="2103" ><b>Title</b></section-title>
                <authors id="2204" >
                        <author id="2205" >
                            <dl>,</dl>  <!--here i want like this-->
                            <!-- correrct the id -->
                            <given-name id="2206" >GivenName </given-name><dl>,</dl><!--here i want like this-->
                            <surname id="2207" >Surname</surname><dl>,</dl><!--here i want like this-->
                        </author>
                    </authors>
                    <title id="2208" >
                        <maintitle id="2209" >technology</maintitle>
                    </title>             
          </biblio>

XSLT, который я написал, это ..

 <xsl:template match="*[@class]">   
    <xsl:element name="{substring-after(@class, 'mps_')}">
        <xsl:copy-of select="@*[not(name()='class')]"/>
        <xsl:if test="not(current())">
        <xsl:apply-templates>    
                            <xsl:sort select="@id" data-type="number"/>   
        </xsl:apply-templates>   
        </xsl:if>
    </xsl:element>
</xsl:template> 

Help me.......

Ответы [ 2 ]

0 голосов
/ 03 февраля 2012

Это преобразование XSLT 1.0 :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ext="http://exslt.org/common" exclude-result-prefixes="ext">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
     <xsl:strip-space elements="*"/>

     <xsl:variable name="vrtfPass1">
       <xsl:apply-templates select="/*"/>
     </xsl:variable>

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

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

     <xsl:template match="/">
      <xsl:apply-templates mode="pass2"
           select="ext:node-set($vrtfPass1)/*"/>
     </xsl:template>

     <xsl:template match="*[@class]" mode="pass2">
      <xsl:element name="{substring-after(@class, 'one_')}">
       <xsl:copy-of select="@*[not(name()='class')]"/>
       <xsl:apply-templates>
         <xsl:sort select="@id" data-type="number"/>
       </xsl:apply-templates>
      </xsl:element>
     </xsl:template>

     <xsl:template match=
      "text()
        [../self::span[@class]
        or
         preceding-sibling::node()[1]
                            [self::span[@class]]
         ]
           [contains(., ',')]">
        <xsl:value-of select="substring-before(., ',')"/>
        <dl>,</dl>
        <xsl:value-of select="substring-after(., ',')"/>
      </xsl:template>
</xsl:stylesheet>

при применении к предоставленному документу XML (исправлено, чтобы оно было правильно сформировано !!!):

<span id="2102" class="one_biblio">
    <span id="2103" class="one_section-title">
        <b>Title</b>
    </span>
    <span id="2204" class="one_authors">
        <span id="2205" class="one_author">, 
            <span id="2207" class="one_surname">Surname</span>,
            <span id="2206" class="one_given-name">GivenName</span>,
        </span>
    </span>
    <span id="2208" class="one_title">
        <span id="2209" class="one_maintitle">technology</span>
    </span>
</span>

дает требуемый, правильный результат :

<biblio id="2102">
   <span id="2103" class="one_section-title">
      <b>Title</b>
   </span>
   <span id="2204" class="one_authors">
      <span id="2205" class="one_author">
         <dl>,</dl> 

         <span id="2207" class="one_surname">Surname</span>
         <dl>,</dl>

         <span id="2206" class="one_given-name">GivenName</span>
         <dl>,</dl>

      </span>
   </span>
   <span id="2208" class="one_title">
      <span id="2209" class="one_maintitle">technology</span>
   </span>
</biblio>

Пояснение : двухпроходное преобразование.Первый проход исправляет запятую, второй проход выполняет остальную часть обработки.

0 голосов
/ 02 февраля 2012

Это довольно грубый подход, который основан на том, что вы знаете имена элементов, за которыми следуют запятые.

Версия 1 - Имена элементов известны

<xsl:template match="*[@class]">    
  <!-- copy the computed element name to a variable for ease of use -->
  <xsl:variable name="elementName" select="substring-after(@class, 'one_')"/>

  <xsl:element name="{$elementName}"> 
    <xsl:copy-of select="@*[not(name()='class')]"/> 

    <!-- insert "author" comma -->
    <xsl:if test="$elementName='author'"><dl>,</dl></xsl:if>

    <!-- process contents -->
      <xsl:apply-templates>     
        <xsl:sort select="@id" data-type="number"/>    
      </xsl:apply-templates>

  </xsl:element> 

  <!-- insert 'given-name' and 'surname' commas -->
  <xsl:if test="$elementName='given-name' or $elementName='surname'"><dl>,</dl></xsl:if>

</xsl:template>  

<!-- strip out the 'author' commas where they would normally end up -->
<xsl:template match="text()[normalize-space(.)=','][ancestor-or-self::*[@class='one_author']"/>

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

Версия 1 - Имена элементов неизвестны

  <xsl:element name="{$elementName}"> 
    <xsl:copy-of select="@*[not(name()='class')]"/> 

    <!-- insert comma if first text child is a comma -->
    <xsl:if test="starts-with(normalize-space(text()[1]), ',')"><dl>,</dl></xsl:if>

    <!-- process contents -->
      <xsl:apply-templates>     
        <xsl:sort select="@id" data-type="number"/>    
      </xsl:apply-templates>
  </xsl:element>         

  <!-- insert comma if the element is immediately followed by a comma -->
  <xsl:if test="normalize-space(following-sibling::text()[1])=','"><dl>,</dl></xsl:if>
</xsl:template>  

<!-- strip out the 'author' commas where they would normally end up -->
<xsl:template match="text()[normalize-space(.)=','][ancestor-or-self::*[@class='one_author']"/>

Будет ли более подходящей версия 2, будет зависеть от того, могут ли содержать другие произвольные элементы, которых вы не знаетезнаю, но также полагается, что нет других элементов, которые начинаются с запятых или сопровождаются запятыми, которые вы не хотите сохранять.

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...