2015-04-02 2 views
0

У меня есть цикл между дочерними узлами я могу иметь слово в ВОК: блок, чем другое слово, как:Написать микс (тег + текст) заменить только конкретный узел

<mynode> 
Hi ok 
<fo:block> 
hi ok fo block 
< /fo:block> 
maybe another text node here... 
</mynode> 

я должен заменить <fo:block> с <div> но я должен оставить текст в том же положении (до и, возможно, после того, как фо: блок, если он существует)

Я пытаюсь этот код, но (допустим к ребенку контура (*) узлы):

<xsl:for-each select="/mynode"> 
    <xsl:if test="text()"><xsl:value-of select="text()"/></xsl:if> 
    <xsl:for-each select="child::*"> 
    <!--for every child node of mynode--> 
    <xsl:choose> 
     <xsl:when test="normalize-space(local-name()) 
         = normalize-space('block')"> 
     <xsl:call-template name="fo-block"> 
      <xsl:with-param .../> 
     </xsl:call-template> 
     </xsl:when> 
    <xsl:otherwise> 
     <xsl:if test="text()"><xsl:value-of select="text()"/></xsl:if> 
    </xsl:otherwise> 
    </xsl:choose> 
</xsl:for-each> 
</xsl:for-each> 

if test = text(), поэтому узел содержит текст, а затем выводит текст, в противном случае я получаю имя узла и проверяю, является ли блок: если это так, я вызываю конкретный шаблон, иначе тест, если содержит текст.

Кажется, что нужно работать на данный момент. Так может быть правильный выбор/код для моего объема?

спасибо!

Роби

ответ

0

Проблемы, которые появляются на первый взгляд, включают:

  • Ваши внутренние для каждой петли-петли над child::*, которые будут соответствовать каждому элементу ребенка; он не будет соответствовать другим детям (текстовые узлы, комментарии, инструкции по обработке). Я думаю, вы имели в виду child::node().

  • Ваш тест для элементов блока ("normalize-space(local-name()) = normalize-space('block')") является пространством без названия, поэтому он излишне хрупкий. Вызов normalize-space() бессмысленны, так как local-name() никогда не возвращает строку, содержащую пробельные символы, а буква «block» не содержит пробелов.

    Более короткий, надежный тест будет test="self::fo:block".

  • Вы говорите

    Seems to work for now.. 
    

    Если тесты показывают, этот код работает, ваши тесты не делают вас столько хорошо, как они должны.

Часть вашей обработки, что вы описываете, кажется, составит: изменение fo:block элементов в div; оставьте все остальное одинаковым. Самый простой способ приблизиться к такому преобразованию - написать преобразование идентичности, а затем добавить более конкретные правила для захвата вещей, которые необходимо изменить. Например:.

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

<!--* other non-identity processing goes here ... *--> 

<!--* What we don't have specific rules for gets handled 
    * by the following template and the default templates, 
    * which together perform an identity transform. *--> 

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

Какова цель двух шаблонов, соответствующих 'комментария()' и 'обработка-инструкция()'? Эти узлы уже обрабатываются шаблоном преобразования идентификаторов.AFAICT, единственным эффектом этих шаблонов является создание сообщения об ошибке «Ошибка: неоднозначное совпадение правил для ...». –

+0

Я подозреваю, что, когда я сделал свою версию удостоверения личности лет назад, я угадал их, потому что я часто хочу рассматривать их отдельно. Они не обрабатываются общим правилом, которое я дал изначально, потому что они не совпадают с шаблоном соответствия '@ * | *' (если только я не пропущу что-то здесь). Но я могу сделать ваше наблюдение истинным и удалить их, если вам нравится –

0

M,

ваша схема и ответ был очень полезным

добавить сложность на мой фо: блок перевод: рассмотрим атрибуты заменены HTML, если им в таблице (в ВОК: клетка родитель) я использую DIV, в противном случае (в любом месте) р .. Итак, я внести эти изменения, надеюсь, что вы согласитесь:

<xsl:template match="fo:block"> 

<xsl:choose> 
<xsl:when test="parent::fo:table-cell"> 
<div> 
    <xsl:apply-templates select="node()"/> 
</div> 
</xsl:when> 
<xsl:otherwise> 
    <xsl:if test="@space-before"> <!-- distance before is rep. by br --> 
     <xsl:call-template name="count-br"> <!-- write a br tag for each unit --> 
      <xsl:with-param name="howmuch"><xsl:value-of select="substring-before(normalize-space(@space-before),'cm')"/></xsl:with-param> 
     </xsl:call-template> 
    </xsl:if> 
<p> 
    <xsl:if test="@font-size"> 
     <xsl:attribute name="font-size"><xsl:value-of select="@font-size"/></xsl:attribute> 
    </xsl:if> 
    <xsl:if test="@text-align"> 
     <xsl:attribute name="text-align"><xsl:value-of select="@text-align"/></xsl:attribute> 
    </xsl:if> 
    <xsl:if test="@font-family"> 
     <xsl:attribute name="font-family"><xsl:value-of select="@font-family"/></xsl:attribute> 
    </xsl:if> 
    <xsl:apply-templates select="node()"/>   
</p> 
</xsl:otherwise> 
</xsl:choose> 
</xsl:template>