2015-01-27 2 views
0

Просьба предложить разделить уравнение на две части на основе первой точки. Раньше я получил suggestion to Split the Equation на основе текста комментария BREAK от michael.hor257k, теперь требуется разделить на период.Разделить уравнение на основе первой точки (.)

XML:

<root> 
    <body><sec><title>The sec 1</title><p>Text 1</p></sec></body> 
    <inline-formula> 
     <math display="inline"> 
      <mi>A</mi> 
      <mn>4.651</mn> 
      <mi>The next text</mi> 
     </math> 
    </inline-formula> 
    <inline-formula> 
     <math display="inline"> 
      <mrow> 
       <mrow><mi>B</mi></mrow> 
       <mrow><mn>4.651</mn></mrow> 
      </mrow> 
      <mi>The next text</mi> 
     </math> 
    </inline-formula> 
</root> 

XSLT:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:variable name="root" select="//inline-formula/*" /> 

    <xsl:template match="/"> 
     <xsl:for-each select="//inline-formula"> 
       <xsl:for-each select="text()"> 
        <xsl:if test="contains(., '.')"> 
         <xsl:apply-templates select="$root"> 
          <xsl:with-param name="i" select="." tunnel="yes"/> 
         </xsl:apply-templates> 
        </xsl:if> 
       </xsl:for-each > 
     </xsl:for-each> 
    </xsl:template> 

    <xsl:template match="@*|node()"> 
     <xsl:param name="i" tunnel="yes"/> 
      <xsl:if test="descendant-or-self::text()[contains(., '.')]"> 
       <xsl:copy> 
        <xsl:apply-templates select="@*|node()"/> 
       </xsl:copy> 
      </xsl:if> 
    </xsl:template> 

</xsl:stylesheet> 

Обязательный Результат:

<root> 
    <body><sec><title>The sec 1</title><p>Text 1</p></sec></body> 
    <inline-formula> 
     <math display="inline"> 
      <mi>A</mi> 
      <mn>4.</mn> 
     </math> 
    </inline-formula> 
    <inline-formula> 
     <math display="inline"> 
      <!--Text node, before dot is removed --> 
      <mn>651</mn> 
      <mi>The next text</mi> 
     </math> 
    </inline-formula> 

    <inline-formula> 
     <math display="inline"> 
      <mrow> 
       <mrow><mi>B</mi></mrow> 
       <mrow><mn>4.</mn></mrow> 
      </mrow> 
     </math> 
    </inline-formula> 
    <inline-formula> 
     <math display="inline"> 
      <mrow> 
       <!--Text node, before dot is removed --> 
       <mrow><mn>651</mn></mrow> 
      </mrow> 
      <mi>The next text</mi> 
     </math> 
    </inline-formula> 
</root> 
+0

Вы потратили некоторое время теперь SO, и в углу XSLT. Пожалуйста, научитесь правильно использовать _tag system_. Вопросы о XSLT 2.0 должны быть отмечены как таковые. –

ответ

1

Глядя на ответ на предыдущий вопрос, предоставленный michael.hor257k, есть несколько ключевых отличий от XSLT, которые вы используете в этом вопросе.В предыдущем ответе, который расщепляется на комментарии, он перебирает количество раз такие комментарии появляются

<xsl:for-each select="0 to count(//comment()[.='Break'])"> 

Таким образом, в новом решении, необходимо перебрать количество раз текстовый узел происходит с точкой в :

<xsl:for-each select="0 to count(//text()[contains(., '.')])"> 

Затем в «идентичности» шаблон, предыдущий ответ проверяет количество комментариев ниже текущего узла, чтобы увидеть, если он показал копироваться:

<xsl:if test="descendant-or-self::text()[count(preceding::comment()[.='Break'])=$i]"> 

Этот мне ANS, в новом решении, вы можете начать с написания этого:

<xsl:if test="descendant-or-self::text()[count(preceding::text()[contains(., '.')])=$i]"> 

Однако, это не было бы совершенно правильно, так как узел с точкой в ​​будет скопировано в первой части раскола, но вторая часть раскола не будет содержать узел вообще.

Реально выражение нужно это:

<xsl:if test="descendant-or-self::text()[(count(preceding::text()[contains(., '.')])=($i - 1) and contains(., '.')) or count(preceding::text()[contains(., '.')])=$i]"> 

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

Попробуйте XSLT

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:variable name="root" select="/*" /> 

<xsl:template match="/*"> 
    <xsl:copy> 
     <xsl:copy-of select="*[not(self::inline-formula)]" /> 
     <xsl:for-each select="0 to count(//text()[contains(., '.')])"> 
      <xsl:apply-templates select="$root/inline-formula"> 
       <xsl:with-param name="i" select="." tunnel="yes"/> 
      </xsl:apply-templates> 
     </xsl:for-each > 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="@*"> 
    <xsl:copy /> 
</xsl:template> 

<xsl:template match="node()"> 
    <xsl:param name="i" tunnel="yes"/> 
    <xsl:if test="descendant-or-self::text()[(count(preceding::text()[contains(., '.')])=($i - 1) and contains(., '.')) or count(preceding::text()[contains(., '.')])=$i]"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:if> 
</xsl:template> 

<xsl:template match="text()[contains(., '.')]"> 
    <xsl:param name="i" tunnel="yes"/> 
    <xsl:choose> 
     <xsl:when test="count(preceding::text()[contains(., '.')]) = $i"> 
      <xsl:value-of select="substring-before(., '.')" /><xsl:text>.</xsl:text> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:value-of select="substring-after(., '.')" /> 
     </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 
</xsl:stylesheet> 
+0

Большое спасибо за предложения и приятное объяснение о коде, отлично работая, +1 –

+0

Одно небольшое уточнение, пожалуйста, уравнения должны разорваться только на первую точку, остальная часть текста или часть уравнения не должны ломаться, даже если уравнение имеет вторую точку в следующий текст. –

+0

Между встроенной формулой, если какой-либо тест представляет, то текст (не уравнение) движется над всеми уравнениями. –

1

Я также интересно, почему вы урожденная d такое преобразование, но вот возможное решение. Правила мне не понятны, например.

  • Может ли быть более 2 mn элементы в inline-formula?
  • Всегда ли это строковое значение mn, которое необходимо разделить на отдельные элементы?
  • Вы говорите, раскол должен происходить на первой. в значении mn, но несколько точек не имеют смысл в одном mn элемента в MathML

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

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

    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:template match="mn[contains(.,'.')]"> 
     <xsl:for-each select="tokenize(.,'\.')"> 
      <mn> 
       <xsl:value-of select="."/> 
       <xsl:if test="position() = 1"> 
        <xsl:text>.</xsl:text> 
       </xsl:if> 
      </mn> 
     </xsl:for-each> 
    </xsl:template> 

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

</xsl:stylesheet> 

промежуточный результат является

<?xml version="1.0" encoding="UTF-8"?> 
<root> 
    <body> 
     <sec> 
     <title>The sec 1</title> 
     <p>Text 1</p> 
     </sec> 
    </body> 
    <inline-formula> 
     <math display="inline"> 
     <mi>A</mi> 
     <mn>4.</mn> 
     <mn>651</mn> 
     <mi>The next text</mi> 
     </math> 
    </inline-formula> 
    <inline-formula> 
     <math display="inline"> 
     <mrow> 
      <mrow> 
       <mi>B</mi> 
      </mrow> 
      <mrow> 
       <mn>4.</mn> 
       <mn>651</mn> 
      </mrow> 
     </mrow> 
     <mi>The next text</mi> 
     </math> 
    </inline-formula> 
</root> 

Затем нанести второе преобразование, аналогичное приведенным ниже. Кстати, это хорошая возможность использовать ключевые слова специального режима #all и #current.

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

    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:template match="inline-formula[count(//mn) gt 1]"> 
     <xsl:apply-templates select="." mode="first"/> 
     <xsl:apply-templates select="." mode="second"/> 
    </xsl:template> 

    <xsl:template match="mn[position() = 2] | mi[. = 'The next text']" mode="first"/> 
    <xsl:template match="mi[. != 'The next text']" mode="second"/> 

    <xsl:template match="mn[position() = 1]" mode="second"> 
     <xsl:comment>Text node, before dot is removed</xsl:comment> 
    </xsl:template> 


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

</xsl:stylesheet> 

и конечный результат

<?xml version="1.0" encoding="UTF-8"?> 
<root> 
    <body> 
     <sec> 
     <title>The sec 1</title> 
     <p>Text 1</p> 
     </sec> 
    </body> 
    <inline-formula> 
     <math display="inline"> 
     <mi>A</mi> 
     <mn>4.</mn> 
     </math> 
    </inline-formula> 
    <inline-formula> 
     <math display="inline"><!--Text node, before dot is removed--> 
     <mn>651</mn> 
     <mi>The next text</mi> 
     </math> 
    </inline-formula> 
    <inline-formula> 
     <math display="inline"> 
     <mrow> 
      <mrow> 
       <mi>B</mi> 
      </mrow> 
      <mrow> 
       <mn>4.</mn> 
      </mrow> 
     </mrow> 
     </math> 
    </inline-formula> 
    <inline-formula> 
     <math display="inline"> 
     <mrow> 
      <mrow/> 
      <mrow><!--Text node, before dot is removed--> 
       <mn>651</mn> 
      </mrow> 
     </mrow> 
     <mi>The next text</mi> 
     </math> 
    </inline-formula> 
</root> 

Результат содержит пустой mrow элемент. Если это имеет значение, вы можете добавить еще один шаблон вдоль линий

<xsl:template match="mrow/mrow[not(mn)]" mode="second"/> 

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

+0

Спасибо за предложение, это одно из живых требований команды Rendering, здесь нам нужно сделать разделение на основе ** FIRST dot **, конечно, это ** MN ** element и '** Следующий текст * * 'может быть любой контент или любое количество элементов, за которым может следовать первый MN (с точкой). –

Смежные вопросы