Хобрук: Ваш путь к мастерству в программировании

Как получить доступ к вложенным дочерним элементам с одинаковыми именами и форматами

Пожалуйста, предложите, как добраться до внутреннего mrow/mo, содержащего фигурные скобки.

В данных примерах фигурные скобки первого уровня правильно преобразуются в «MFENCED» при mrow (если его первый и последний дочерние элементы должны быть «MO» со знаками фигурных скобок). Но невозможно изменить скобки второго уровня, где они также имеют «MFRAC» в качестве потомка. Шаблон должен совпадать с 'MROW' (как указано).

Ввод XML:

<article>
<body>
<math id="m1">
    <mrow>
      <mo>(</mo><!--first level braces open-->
        <mi>u</mi>
        <mo>+</mo>
        <mi>g</mi>
        <mi>=</mi>
        <mrow>
            <mo>(</mo><!--second level braces open-->
            <mfrac>
                <mrow><mn>1</mn></mrow>
                <mrow><mn>2</mn></mrow>
            </mfrac>
            <mo>)</mo><!--second level braces close-->
        </mrow>
      <mo>)</mo><!--first level braces close-->
    </mrow>
</math>

<math id="m2">
    <mrow>
        <mo>(</mo>
            <mrow>
                <mfrac>
                    <mn>8</mn>
                    <mn>9</mn>
                </mfrac>
            </mrow>
        <mo>)</mo>
    </mrow>
</math>
</body>
</article>

XSLT 2.0:

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

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

<xsl:template match="mrow[matches(child::*[1][name()='mo'], '^(\(|\[|\{)$')]
                            [matches(child::*[position()=last()][name()='mo'], '^(\)|\]|\})$')]">
    <xsl:choose>
        <xsl:when test="descendant::mfrac">
            <xsl:copy>
                <xsl:element name="mfenced">
                    <xsl:attribute name="open"><xsl:value-of select="child::*[1][name()='mo']"/></xsl:attribute>
                    <xsl:attribute name="close"><xsl:value-of select="child::*[position()=last()][name()='mo']"/></xsl:attribute>
                        <xsl:for-each select="*">
                            <xsl:if test="position()=1"/>
                            <xsl:if test="not(position()=1) and not(position()=last())">
                                <xsl:copy><xsl:apply-templates select="@* | node()"/></xsl:copy>
                            </xsl:if>
                            <xsl:if test="position()=last()"/>
                        </xsl:for-each>
                </xsl:element>
            </xsl:copy>
        </xsl:when>
        <xsl:otherwise>
            <xsl:copy><xsl:apply-templates select="@* | node()"/></xsl:copy>
        </xsl:otherwise>
        </xsl:choose>
</xsl:template>
</xsl:stylesheet>

Необходимый результат:

<article>
<body>
<math id="m1">
    <mrow>
        <mfenced open="(" close=")"><mi>u</mi><mo>+</mo><mi>g</mi><mi>=</mi>
            <mrow>
            <mfenced open="(" close=")"><!-- this node or modification required, because, within this MFRAC presents, then it should convert to 'MFENCED' -->
                <mfrac>
                    <mrow><mn>1</mn></mrow>
                    <mrow><mn>2</mn></mrow>
                </mfrac>
            </mfenced>
            </mrow>
        </mfenced>
    </mrow>
</math>

<math id="m2">
    <mrow>
        <mfenced open="(" close=")">
            <mrow>
                <mfrac>
                    <mn>8</mn>
                    <mn>9</mn>
                </mfrac>
            </mrow>
        </mfenced>
    </mrow>
</math>
</body>
</article>
05.06.2017

Ответы:


1

Я думаю, вы можете использовать xsl:for-each-group group-starting-with/group-ending-with следующим образом:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">

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

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

    <xsl:template match="mrow[mo = '(']">
        <xsl:copy>
            <xsl:for-each-group select="*" group-starting-with="mo[. = '(']">
                <xsl:choose>
                    <xsl:when test="self::mo[. =  '(']">
                        <xsl:for-each-group select="current-group() except ." group-ending-with="mo[. = ')']">
                            <xsl:choose>
                                <xsl:when test="current-group()[last()][self::mo[. = ')']]">
                                    <mfenced open="(" close=")">
                                        <xsl:apply-templates select="current-group()[not(position() eq last())]"/>
                                    </mfenced>
                                </xsl:when>
                                <xsl:otherwise>
                                    <xsl:apply-templates select="current-group()"/>
                                </xsl:otherwise>
                            </xsl:choose>
                        </xsl:for-each-group>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:apply-templates select="current-group()"/>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:for-each-group>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

Это дает

<?xml version="1.0" encoding="UTF-8"?>
<article>
   <body>
      <math id="m1">
         <mrow>
            <mfenced open="(" close=")">
               <mi>u</mi>
               <mo>+</mo>
               <mi>g</mi>
               <mi>=</mi>
               <mrow>
                  <mfenced open="(" close=")">
                     <mfrac>
                        <mrow>
                           <mn>1</mn>
                        </mrow>
                        <mrow>
                           <mn>2</mn>
                        </mrow>
                     </mfrac>
                  </mfenced>
               </mrow>
            </mfenced>
         </mrow>
      </math>
      <math id="m2">
         <mrow>
            <mfenced open="(" close=")">
               <mrow>
                  <mfrac>
                     <mn>8</mn>
                     <mn>9</mn>
                  </mfrac>
               </mrow>
            </mfenced>
         </mrow>
      </math>
   </body>
</article>
05.06.2017
  • Спасибо за предложение, плюс один за хороший метод группировки. 05.06.2017
  • И одно сомнение-сэр, почему второй MROW тоже дочерний, почему он не достигается в -for-each select=*. Пожалуйста, предложите. 05.06.2017
  • Ваш вопрос связан с моим кодом XSLT? Или к тому, что в вашем вопросе? Если у вас есть входной образец, для которого мое предложение не работает, рассмотрите возможность отредактировать свой вопрос и показать его. 05.06.2017
  • Нет, сэр, в моем коде xslt также используются for-each select=* и ‹xsl:apply-templates/›. Тогда этот второй MROW тоже можно модифицировать? (мой код XSLT). Ваше предложение работает для многих форматов, даже для разнородных фигурных скобок. 05.06.2017
  • Новые материалы

    ВЫ РЕГРЕСС ЭТО?
    Чтобы понять, когда использовать регрессионный анализ, мы должны сначала понять, что именно он делает. Вот простой ответ, который появляется, когда вы используете Google: Регрессионный..

    Не зря же это называют интеллектом
    Стек — C#, Oracle Опыт — 4 года Работа — Разведывательный корпус Мне пора служить Может быть, я немного приукрашиваю себя, но там, где я живу, есть обязательная военная служба на 3..

    LeetCode Проблема 41. Первый пропущенный положительный результат
    LeetCode Проблема 41. Первый пропущенный положительный результат Учитывая несортированный массив целых чисел, найдите наименьшее пропущенное положительное целое число. Пример 1: Input:..

    Расистский и сексистский робот, обученный в Интернете
    Его ИИ основан на предвзятых данных, которые создают предрассудки. Он словно переходит из одного эпизода в другой из серии Черное зеркало , а вместо этого представляет собой хронику..

    Управление состоянием в микрофронтендах
    Стратегии бесперебойного сотрудничества Микро-фронтенды — это быстро растущая тенденция в сфере фронтенда, гарантирующая, что удовольствие не ограничивается исключительно бэкэнд-системами..

    Декларативное и функциональное программирование в стиле LINQ с использованием JavaScript с использованием каррирования и генератора ...
    LINQ - одна из лучших функций C #, которая обеспечивает элегантный способ написания кода декларативного и функционального стиля, который легко читать и понимать. Благодаря таким функциям ES6,..

    Структуры данных в C ++ - Часть 1
    Реализация общих структур данных в C ++ C ++ - это расширение языка программирования C, которое поддерживает создание классов, поэтому оно известно как C с классами . Он используется для..