Преобразование XHTML из узла XML и шаблонов вызовов, передавая XHTML в качестве контекста - PullRequest
0 голосов
/ 24 января 2019

Как преобразовать XHTML из узла XML, а затем вызвать шаблоны, как если бы узел XML являлся родителем XHTML.

Ссылаясь на мой код ниже, я хочу взять значения из group / Clob / text (), преобразованные в XHTML / XML, и продолжить обработку этих новых узлов в соответствии с шаблонами ... такими как центральный шаблон.

Это позволит мне достичь своей общей цели - преобразовать XML из набора данных, который содержит значения Clob из редактора форматированного текста, а затем создает файл XSL: FO, который затем используется для создания PDF.

Подробности ниже должно быть достаточно, чтобы проиллюстрировать то, что я пытался выполнить.

<!--XML-->
<root>

  <group>
    <key>16692504</key>
    <Clob>&lt;body&gt;Testing se&lt;font color="#99cc00"&gt;co&lt;/font&gt;nd o&lt;font color="#99cc00" style="background-color: #000000;"&gt;bser&lt;/font&gt;vation&lt;/body&gt;</Clob>
  </group>
  <group>
    <key>16692508</key>
    <Clob>&lt;body&gt;Testing se&lt;font color="#99cc00"&gt;co&lt;/font&gt;nd o&lt;font color="#99cc00" style="background-color: #000000;"&gt;bser&lt;/font&gt;vation&lt;/body&gt;</Clob>
  </group>

</root>

Вот файл XSL, который я использую для преобразования экранированного содержимого в узле Clob обратно в исходный формат: HTML / XHTML.

<!--xsl-->
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" version="1.0">

<xsl:template name="group"> 
    <xsl:for-each select="//group">

        <xsl:apply-templates mode="unescaped" select="Clob"/>

    </xsl:for-each>
</xsl:template>

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

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

  <xsl:template match="text()">
    <xsl:variable name="escaped-text">
      <xsl:call-template name="replace-string">
        <xsl:with-param name="text" select="."/>
        <xsl:with-param name="replace" select="'&quot;'"/>
        <xsl:with-param name="with" select="'\&quot;'"/>
      </xsl:call-template>
    </xsl:variable>
    <xsl:choose>
        <xsl:when test="parent::*[name() = 'Clob']"> <!-- Converts escaped characters in this node back to XHTML/XML -->
        <xsl:value-of disable-output-escaping="yes" select="normalize-space(.)"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of disable-output-escaping="no" select="normalize-space(.)"/> <!-- Preserves escaping for non essential fields -->
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template name="replace-string">
    <xsl:param name="text"/>
    <xsl:param name="replace"/>
    <xsl:param name="with"/>
    <xsl:choose>
      <xsl:when test="contains($text,$replace)">
        <xsl:value-of select="substring-before($text,$replace)"/>
        <xsl:value-of select="$with"/>
        <xsl:call-template name="replace-string">
          <xsl:with-param name="text" select="substring-after($text,$replace)"/>
          <xsl:with-param name="replace" select="$replace"/>
          <xsl:with-param name="with" select="$with"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:choose>
         <xsl:when test="parent::*[name() = 'Clob']">
            <xsl:value-of disable-output-escaping="yes" select="$text"/>
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of disable-output-escaping="no" select="$text"/>
          </xsl:otherwise>
        </xsl:choose>
     </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

   <xsl:template match="body">
    <fo:block text-align="body">
      <xsl:apply-templates select="*|text()"/>
    </fo:block>
  </xsl:template>  

</xsl:stylesheet>

Когда я возвращаю XML в вывод ниже, я хочу шаблоны вызовов для (включая его атрибуты) и в конечном итоге возвращаю контекст из этих шаблонов.

<!-- Desired XML Output for further processing -->
<root>

  <group>
    <key>16692504</key>
    <Clob><![CDATA[<body><h1>Testing<br /><br /><font color="#00ff00">testing</font><br /><br /><font color="#ffff00">testing</font></h1></body>]]></Clob>
  </group>
  <group>
    <key>16692508</key>
    <Clob><body>Testing se<font color="#99cc00">co</font>nd o<font color="#99cc00" style="background-color: #000000;">bser</font>vation</body>]]></Clob>
  </group>

</root>

В конце концов, это поможет мне сгенерировать шаблоны XSL: FO, которые затем используются для создания PDF-файлов. Это даст мне возможность предоставлять поля форматированного текста HTML, отформатированные специально для XSL: FO, чтобы преобразовать HTML в его эквивалент.

Я использую таблицу стилей XSL: FO и руководство, разработанное Дугом Тидвеллом в IBM, что добавило препятствия к тому, чтобы называть его шаблоном из моей основной таблицы стилей XSL. Вот подробности для этой таблицы стилей.

https://www.ibm.com/developerworks/library/x-xslfo2app/index.html#artdownload

1 Ответ

0 голосов
/ 24 января 2019

XslCompiledTransform позволяет вам использовать расширение "script" в C # или VB.NET с элементом msxsl:script или объектами расширения, переданными с https://docs.microsoft.com/en-us/dotnet/api/system.xml.xsl.xsltargumentlist.addextensionobject?view=netframework-4.7.2#System_Xml_Xsl_XsltArgumentList_AddExtensionObject_System_String_System_Object_, поэтому в теории вы можете легко написать функцию на C #, которая принимает аргумент string, передает его XPathDocument через StringReader строкового аргумента (https://docs.microsoft.com/en-us/dotnet/api/system.xml.xpath.xpathdocument.-ctor?view=netframework-4.7.2#System_Xml_XPath_XPathDocument__ctor_System_IO_TextReader_) и возвращает CreateNavigator() в XPathDocument из функции C # (то есть XPathNavigator). Затем XSLT может вызывать эту функцию и использовать обычную навигацию XPath или обработку шаблонов, как с любым другим входным документом.

Позволяет ли ваша настройка включить обработку "сценария" на XslCompiledTransform (https://docs.microsoft.com/en-us/dotnet/api/system.xml.xsl.xsltsettings.enablescript?view=netframework-4.7.2#System_Xml_Xsl_XsltSettings_EnableScript) или позволяет вам установить объект расширения на XsltArgumentList, который вы передаете методу Transform XslCompiledTransform Я не могу сказать, но код C # довольно прост

public XPathNavigator ParseXml(string xmlCode)
{
  using (StringReader sr = new StringReader(xmlCode))
  {
    return new XPathDocument(sr).CreateNavigator();
  }
}

XPathNavigator даже позволяет вам анализировать фрагменты, если необходимо, если вы используете XmlReader вместо StringReader, так что реализация чего-либо в соответствии с XPath 3.1 parse-xml-fragment также будет возможна.

...