Преобразование изменения регистра XSLT удаляет тег от xml - PullRequest
0 голосов
/ 06 февраля 2020

Я делаю верхний регистр содержимого первого символа в данных xml, используя разделители (пробел и дефис), и могу правильно получить вывод, однако этот шаблон удаляет разрывную строку тег в таблице td области xml. Выходные данные должны быть xml.

eg:<text>
                    <table>
                            <tbody>
                                <tr>
                                    <td>test<br />testing<br />tested</td>
                                </tr>

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

<text>
                    <table>
                            <tbody>
                                <tr>
                                    <td>Testtestingtested</td>
                                </tr>

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

Я использую приведенное ниже преобразование xslt:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
xmlns:n1="urn:hl7-org:v3" xmlns:n2="urn:hl7-org:sdtc">

  <xsl:output method="xml" indent="yes"/>

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

    <xsl:template match='n1:ClinicalDocument/n1:component/n1:structuredBody/n1:component/n1:section/n1:text/n1:table/n1:tbody/n1:tr'>
    <xsl:copy>
      <xsl:apply-templates select='n1:td'/>
    </xsl:copy>
  </xsl:template>

 <xsl:template match="n1:td">
      <xsl:copy>
        <xsl:if test="./@ID">
          <xsl:attribute name="ID" xml:space="default">
            <xsl:value-of select="./@ID"/>
          </xsl:attribute>
        </xsl:if>             
          <xsl:call-template name="capitalize">
            <xsl:with-param name="text" select="string(.)"/>
          </xsl:call-template>
       </xsl:copy>
    <xsl:text>&#xd;</xsl:text>
  </xsl:template>


<xsl:template name="capitalize">
    <xsl:param name="text" />
    <xsl:param name="delimiter" select = "' '"/>      
    ​
    <xsl:variable name="upper-case" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
    <xsl:variable name="lower-case" select="'abcdefghijklmnopqrstuvwxyz'"/>

    <xsl:variable name="word" select="substring-before(concat($text, $delimiter), $delimiter)" />
    <xsl:choose>
       <xsl:when test="$delimiter=' '">
            <!-- tokenize word by 2nd delimiter -->
            <xsl:call-template name="capitalize">
                <xsl:with-param name="text" select="$word"/>
                <xsl:with-param name="delimiter" select="'-'"/>
            </xsl:call-template>
       </xsl:when>
       <xsl:otherwise>
        <!-- capitalize word -->
          <xsl:value-of select="translate(substring($word, 1, 1), $lower-case, $upper-case) " />
          <xsl:value-of select="translate(substring($word, 2), $upper-case, $lower-case)" />
        </xsl:otherwise>
    </xsl:choose>
    <xsl:if test="contains($text, $delimiter)">
      <xsl:value-of select="$delimiter"/>
      <!-- recursive call -->
      <xsl:call-template name="capitalize">
        <xsl:with-param name="text" select="substring-after($text, $delimiter)"  />
      </xsl:call-template>      
    </xsl:if>   
  </xsl:template>  

</xsl:stylesheet>

Может кто-нибудь проверить и ответить?

Ответы [ 2 ]

0 голосов
/ 07 февраля 2020

ОБНОВЛЕНИЕ: оба решения XSLT 1.0 и 2.0

Все решения сохраняют ваши разрывы строк и также работают, если у вас есть встроенная разметка текстового содержимого.

Первый I сделайте параметры l c и u c глобальными для более миниатюрных шаблонов:

<xsl:param name="lc" select="'abcdefghijklmnopqrstuvwxyzàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿžšœ'"/>
<xsl:param name="uc" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞŸŽŠŒ'"/>

XSLT 1.0 или 2.0 : вам нужно переписать свой первый шаблон для этого независимо от следующие решения XSLT:

<xsl:template match="n1:td">
   <xsl:copy>
      <xsl:if test="./@ID">
         <xsl:attribute name="ID" xml:space="default">
            <xsl:value-of select="./@ID"/>
         </xsl:attribute>
      </xsl:if>             
      <xsl:apply-templates select="node()" />
   </xsl:copy>
   <xsl:text>&#xd;</xsl:text>
</xsl:template>

XSLT 1.0

В XSLT 1.0 вам нужно объединить шаблон соответствия с шаблоном имени.

Шаблон соответствия : n1: td // text ()

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

<xsl:template match="n1:td//text()" >
    <xsl:param name="text" select="." />
    <xsl:param name="currentTextBlock" select="ancestor::n1:td[1]" />
    <xsl:param name="isFirstTextNode">
        <xsl:choose>
            <xsl:when test="preceding::text()[ancestor::n1:td[generate-id(.) = generate-id($currentTextBlock)]]">false</xsl:when>
            <xsl:otherwise>true</xsl:otherwise>
        </xsl:choose>
    </xsl:param>
    <xsl:choose>
        <xsl:when test="$isFirstTextNode = 'true'">
            <xsl:value-of select="translate(substring($text, 1, 1), $lc, $uc)" />
            <xsl:call-template name="capitalize">
                <xsl:with-param name="text" select="$text" />
                <xsl:with-param name="remainingText" select="substring($text,2)" />
                <xsl:with-param name="index" select="2" />
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <xsl:call-template name="capitalize">
                <xsl:with-param name="text" select="$text" />
                <xsl:with-param name="remainingText" select="$text" />
                <xsl:with-param name="index" select="1" />
            </xsl:call-template>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

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

<xsl:template match="n1:td//text()" >
    <xsl:param name="text" select="." />
    <xsl:value-of select="translate(substring($text, 1, 1), $lc, $uc)" />
    <xsl:call-template name="capitalize">
        <xsl:with-param name="text" select="$text" />
        <xsl:with-param name="remainingText" select="substring($text,2)" />
        <xsl:with-param name="index" select="2" />
    </xsl:call-template>
</xsl:template>

Шаблон имени: прописные буквы

Это имя Шаблон можно использовать как есть с обоими Шаблоны соответствия и - верхний регистр:

<xsl:template match="n1:td//text()" >
  <xsl:param name="text" select="." />
  <xsl:param name="currentTextBlock" select="ancestor::n1:td[1]" />
  <xsl:param name="isFirstTextNode">
     <xsl:choose>
        <xsl:when test="preceding::text()[ancestor::n1:td[generate-id(.) = generate-id($currentTextBlock)]]">false</xsl:when>
        <xsl:otherwise>true</xsl:otherwise>
     </xsl:choose>
  </xsl:param>
  <xsl:for-each select="tokenize(replace(replace($text,'(.)','$1\\n'),'\\n$',''),'\\n')">
     <xsl:variable name="pos" select="position()" />
     <xsl:variable name="char" select="." />
     <xsl:choose>
        <xsl:when test="$isFirstTextNode = 'true' and $pos = 1">
           <xsl:value-of select="translate($char, $lc, $uc) " />
        </xsl:when>
        <xsl:when test="substring($text, $pos - 1, 1) = ' ' or substring($text, $pos - 1, 1) = '-'">
           <xsl:value-of select="translate($char, $lc, $uc) " />
        </xsl:when>
        <xsl:otherwise>
           <xsl:value-of select="translate($char, $uc, $lc)" />
        </xsl:otherwise>
     </xsl:choose>
  </xsl:for-each>
</xsl:template>

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

<xsl:template match="n1:td//text()" >
  <xsl:param name="text" select="." />
  <xsl:param name="currentTextBlock" select="ancestor::n1:td[1]" />
  <xsl:for-each select="tokenize(replace(replace($text,'(.)','$1\\n'),'\\n$',''),'\\n')">
     <xsl:variable name="pos" select="position()" />
     <xsl:variable name="char" select="." />
     <xsl:choose>
        <xsl:when test="$pos = 1">
           <xsl:value-of select="translate($char, $lc, $uc) " />
        </xsl:when>
        <xsl:when test="substring($text, $pos - 1, 1) = ' ' or substring($text, $pos - 1, 1) = '-'">
           <xsl:value-of select="translate($char, $lc, $uc) " />
        </xsl:when>
        <xsl:otherwise>
           <xsl:value-of select="translate($char, $uc, $lc)" />
        </xsl:otherwise>
     </xsl:choose>
  </xsl:for-each>
</xsl:template>
0 голосов
/ 06 февраля 2020

Проблема в том, что вы вызываете string(.), который принимает строковое значение элемента: это удаляет всю разметку.

Вы должны выполнить рекурсивное снижение, используя xsl:apply-templates на каждом уровне, чтобы применить шаблонные правила для дочерних узлов, вплоть до конечных текстовых узлов, а затем ваше шаблонное правило для текстовых узлов должно выполнять преобразование регистра.

За исключением того, что ваш capitalize logi c кажется пытаться сделать что-то умное (я не уверен, что), что означает, что может потребоваться посмотреть что-то большее, чем один текстовый узел Возможно, вам понадобится другое правило для первого текстового узла и для последующих текстовых узлов: трудно быть уверенным, не увидев спец. c.

. Другой подход к решению этой проблемы состоит в том, чтобы сделать несколько проходов: первый проход заменяет элементы <br/> некоторым текстовым маркером, например, «§br§», на следующем этапе вы обрабатываете текст как строку, а затем, наконец, конвертируете маркеры обратно в узлы элемента.

С XSLT 3.0 вы можете сделать первый проход, используя fn:serialize(), и последний проход, используя fn:parse-xml-fragment(); тогда «текстовым маркером» будет фактическая лексическая разметка "<br/>" в виде строки из пяти символов. (Но будьте осторожны, чтобы не использовать его!)

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