2013-11-19 2 views
1

я следующий XMLразбор строки в XSLT

<xml> 
<xref> 
is determined &ldquo;in prescribed manner&rdquo; 
</xref> 
</xml> 

Я хочу, чтобы увидеть, если мы можем обработать XSLT 2 и возвращает следующий результат

<xml> 
<xref> 
    is 
</xref> 
<xref> 
    determined 
</xref> 
<xref> 
    &ldquo;in prescribed manner&rdquo; 
</xref> 
</xml> 

Я попробовал несколько вариантов, как заменить пространство и объекты а затем использовать для каждого цикла, но не в состоянии его выполнить. Возможно, мы можем использовать tokenize функцию xslt 2.0, но не знаем, как ее использовать. Любой намек будет полезен.

+0

Покажите нам, что вы пытались, пожалуйста. –

ответ

0

@ JimGarrison: Извините, я не удержался. :-) Это XSLT, безусловно, не элегантный, но это (я предполагаю) большая часть работы:

<?xml version="1.0" encoding="UTF-8"?> 
<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:variable name="left_quote" select="'&lt;'"/> 
    <xsl:variable name="right_quote" select="'&gt;'"/> 

    <xsl:template name="protected_tokenize"> 
    <xsl:param name="string"/> 

    <xsl:variable name="pattern" select="concat('^([^', $left_quote, ']+)(', $left_quote, '[^', $right_quote, ']*', $right_quote,')?(.*)')"/> 

    <xsl:analyze-string select="$string" regex="{$pattern}"> 
     <xsl:matching-substring> 

     <!-- Handle the prefix of the string up to the first opening quote by "normal" tokenizing. --> 
     <xsl:variable name="prefix" select="concat(' ', normalize-space(regex-group(1)))"/> 
     <xsl:for-each select="tokenize(normalize-space($prefix), ' ')"> 
      <xref> 
      <xsl:value-of select="."/> 
      </xref> 
     </xsl:for-each> 

     <!-- Handle the text between the quotes by simply passing it through. --> 
     <xsl:variable name="protected_token" select="normalize-space(regex-group(2))"/> 
     <xsl:if test="$protected_token != ''"> 
      <xref> 
      <xsl:value-of select="$protected_token"/> 
      </xref> 
     </xsl:if> 

     <!-- Handle the suffix of the string. This part may contained protected tokens again. So we do it recursively. --> 
     <xsl:variable name="suffix" select="normalize-space(regex-group(3))"/> 
     <xsl:if test="$suffix != ''"> 
      <xsl:call-template name="protected_tokenize"> 
      <xsl:with-param name="string" select="$suffix"/> 
      </xsl:call-template> 
     </xsl:if> 

     </xsl:matching-substring> 
    </xsl:analyze-string> 
    </xsl:template> 

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

    <xsl:template match="xref"> 
    <xsl:call-template name="protected_tokenize"> 
     <xsl:with-param name="string" select="text()"/> 
    </xsl:call-template> 
    </xsl:template> 

</xsl:stylesheet> 

Примечание:

  • Существует общее предположение, что белое пространство служит только в качестве маркеров разделителя и их не нужно сохранять.
  • &ldquo; и rdquo;, по-видимому, недействительны в XML, хотя они действительны в HTML. В XSLT определены переменные, содержащие символы кавычек. Их нужно будет адаптировать, как только вы найдете правильное представление XML. Вы также можете устранить переменные и поместить символы в шаблон регулярного выражения. Это будет значительно упрощено.
  • <xsl:analyze-string> не допускает регулярное выражение, которое может оцениваться в пустую строку. Это становится небольшой проблемой, поскольку либо префикс, и/или защищенный токен, и/или суффикс могут быть пустыми. Я позабочусь об этом, искусственно добавляя пространство в начале шаблона, которое позволяет мне искать префикс, используя + (по крайней мере одно вхождение) вместо * (ноль или более случаев).
+0

@atif: Можно ли считать, что символы цитирования всегда хорошо сбалансированы? Если нет, возможно, мне придется внести еще одно незначительное изменение в мое решение. –

+0

@atif: Это работает? –

+0

Спасибо, Маркус, это действительно сработало. – atif