Преобразование строки XSLT в узел и экранирование вывода отключений

Я экспортирую базу данных Access в XML, затем мне нужно преобразовать XML, чтобы подготовить данные для Framemaker для создания публикации. В процессе мне нужно создать перекрестные ссылки в тексте вывода Access. На данный момент мой подход заключается в вставке <idref>некоторого текста</idref>, но при экспорте в XML это превращается в &amp;lt;некоторый текст&amp;gt;, и из-за этого синтаксический анализатор html, который я использую, выглядит следующим образом: не конвертируя текст в узел, как мне хотелось бы. У меня Saxon EE 9.8.3, но я не тестировал анализ html, поскольку решение, представленное в предыдущем вопросе, помогло решить мои первоначальные проблемы с анализом. (Использование parse-xml для преобразования текста в узел XML)

Вот версия ввода XML:

<?xml version = "1.0" encoding = "UTF-8"?>
<dataroot xmlns:od = "urn:schemas-microsoft-com:officedata" generated = "2023-09-29T08:29:47">
<TEQuery>
<IntID>PR090F</IntID>
<TEName>Exempt Lease From Taxable Owner</TEName>
<Description>
&lt;div&gt;&lt;font face=&quot;Times New Roman&quot; color=black&gt;&amp;nbsp;Leased &amp;lt;idref&amp;gt;PR001F&amp;lt;/idref&amp;gt; properties that qualify for this exemption are reported under one of the following expenditures: &lt;/font&gt;&lt;/div&gt;

&lt;ul&gt;
 &lt;ul&gt;
  &lt;ul&gt;
   &lt;ul&gt;
    &lt;ul&gt;
     &lt;ul&gt;
      &lt;ul&gt;
       &lt;li&gt;&lt;font face=&quot;Times New Roman&quot; color=black&gt;&amp;lt;idref&amp;gt;PR001F&amp;lt;/idref&amp;gt;, &lt;/font&gt;&lt;/li&gt;
       &lt;li&gt;&lt;font face=&quot;Times New Roman&quot; color=black&gt;PR007F, &lt;/font&gt;&lt;/li&gt;
       &lt;li&gt;&lt;font face=&quot;Times New Roman&quot; color=black&gt;PR079F, &lt;/font&gt;&lt;/li&gt;
       &lt;li&gt;&lt;font face=&quot;Times New Roman&quot; color=black&gt;PR083F, &lt;/font&gt;&lt;/li&gt;
       &lt;li&gt;&lt;font face=&quot;Times New Roman&quot; color=black&gt;PR085F, &lt;/font&gt;&lt;/li&gt;
       &lt;li&gt;&lt;font face=&quot;Times New Roman&quot; color=black&gt;PR086F, &lt;/font&gt;&lt;/li&gt;
       &lt;li&gt;&lt;font face=&quot;Times New Roman&quot; color=black&gt;PR087F, .&lt;/font&gt;&lt;/li&gt;
      &lt;/ul&gt;
     &lt;/ul&gt;
    &lt;/ul&gt;
   &lt;/ul&gt;
  &lt;/ul&gt;
 &lt;/ul&gt;
&lt;/ul&gt;</Description>
<TaxSort>2</TaxSort>
</TEQuery>
</dataroot>

Мой желаемый результат:

<dataroot xmlns:od = "urn:schemas-microsoft-com:officedata"
          generated = "2023-09-26T10:37:15">

   <TaxExpenditure id = "PR090F" TAXSORT = "2">Exempt Lease From Taxable Owner
      <Description>
Leased <idref>PR001F</idref> properties that qualify for this exemption are reported under one of the following expenditures:
<unorderedList>
            <listitem><idref>PR001F</idref>, </listitem>
            <listitem>PR007F, </listitem>
            <listitem>PR079F, </listitem>
            <listitem>PR083F, </listitem>
            <listitem>PR085F, </listitem>
            <listitem>PR086F, </listitem>
            <listitem>PR087F, </listitem>
         </unorderedList>
   </TaxExpenditure>
</dataroot>

На самом деле у меня есть «решение»: я могу использовать экранирование отключения вывода, но я видел в другом месте, что это более продвинутый инструмент, и часто это не идеальное решение. Это лучший подход к решению моей проблемы?

*Обратите внимание, что я использую htmlparse Дэвида Карлайла, который можно использовать с XSLT 2.0.

Вот XSLT, который я использую:

<xsl:stylesheet version = "3.0" xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
  xmlns:dc = "data:,dpc"
  exclude-result-prefixes = "#all">
  
<xsl:output method = "xml" omit-xml-declaration = "yes" encoding = "UTF-8" indent = "yes" />

<xsl:import href = "https://raw.githubusercontent.com/davidcarlisle/web-xslt/main/htmlparse/htmlparse.xsl"/>

<xsl:mode on-no-match = "shallow-copy"/>

<xsl:template match = "TEQuery">
    <TaxExpenditure>
      <xsl:attribute name = "id" select = "IntID"/>
      <xsl:attribute name = "TAXSORT" select = "TaxSort"/>
      <xsl:value-of select = "TEName"/>
      <xsl:apply-templates select = "@* | node()" />
    </TaxExpenditure>
</xsl:template>

<xsl:template match = "Description">
  <xsl:copy>
    <xsl:apply-templates select = "dc:htmlparse(., '', true())"/>
  </xsl:copy>
</xsl:template>

<xsl:template match = "li">
  <listitem>
    <xsl:value-of disable-output-escaping = "yes"   select = "."/>
  </listitem>
</xsl:template>

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

<xsl:template match = "ul[ul] | font | div">
  <xsl:apply-templates/>
</xsl:template>

<xsl:template match = "ul[not(ul)]">
  <unorderedList>
    <xsl:apply-templates/>
  </unorderedList>
</xsl:template>

<xsl:template match = "IntID"/>
<xsl:template match = "TaxSort"/>
<xsl:template match = "TEName"/>
</xsl:stylesheet>

Вы говорите: «Мой подход состоит в том, чтобы вставить <idref>некоторый текст</idref>», но неясно, во что и как вы это вставляете. Если это в конечном итоге будет экранировано, это будет выглядеть так, как будто вы вставляете лексический XML в виде текста в проанализированную древовидную структуру XML. Если у вас есть проанализированная древовидная структура, вы должны вставлять в нее узлы, а не лексические строки XML.

Michael Kay 29.09.2023 19:14

Итак, в базе данных Access мне нужно иметь возможность разрешить пользователям добавлять какой-то текст, который после преобразования в XML и последующего преобразования превратится в узел xml. Тот точный текст, который я добавляю в ячейку базы данных и который вы процитировали, затем преобразуется при экспорте в формате XML в то, что отображается в моем входном XML. Думаю, я понимаю, что вы говорите о лексическом XML и узлах, но я не знаю, как обойти это из-за рабочего процесса, который у меня есть через Access, поэтому я думаю, что цель состоит в том, чтобы преобразовать эту лексическую строку в узел.

MadeFrame 29.09.2023 20:33
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ваш xslt уже дает ожидаемый результат. Но я вижу 2 альтернативы

Кажется, что dc:htmlparse может обрабатывать все виды (недопустимого) HTML, так почему бы не вызвать dc:htmlparse еще раз на <xsl:template match = "li"> вот так:

  <xsl:template match = "li">
    <listitem>
      <xsl:apply-templates select = "dc:htmlparse(., '', true())"/>
    </listitem>
  </xsl:template>

Если вы уверены, что вставляете действительный XML, вы также можете использовать:

  <xsl:template match = "li">
    <listitem>
      <xsl:apply-templates select = "parse-xml-fragment(.)"/>
    </listitem>
  </xsl:template>

РЕДАКТИРОВАТЬ

Этот xslt будет иметь дело с рекурсивным экранированным XML:

<xsl:stylesheet version = "3.0" xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" xmlns:dc = "data:,dpc" exclude-result-prefixes = "#all">
  
  <xsl:output method = "xml" omit-xml-declaration = "yes" encoding = "UTF-8" indent = "yes" />
  <xsl:import href = "https://raw.githubusercontent.com/davidcarlisle/web-xslt/main/htmlparse/htmlparse.xsl"/>
  <xsl:mode on-no-match = "shallow-copy"/>
  
  <xsl:template match = "TEQuery">
    <TaxExpenditure>
      <xsl:attribute name = "id" select = "IntID"/>
      <xsl:attribute name = "TAXSORT" select = "TaxSort"/>
      <xsl:value-of select = "TEName"/>
      <xsl:apply-templates select = "@* | node()" />
    </TaxExpenditure>
  </xsl:template>
  
  <!-- This template does (optional recursively) what you need without the need of matching specific elements-->
  <xsl:template match = "text()[contains(.,'&lt;')]">
    <xsl:apply-templates select = "dc:htmlparse(., '', true())"/>
  </xsl:template>
  
  <xsl:template match = "ul[ul] | font | div">
    <xsl:apply-templates/>
  </xsl:template>
  
  <xsl:template match = "ul[not(ul)]">
    <unorderedList>
      <xsl:apply-templates/>
    </unorderedList>
  </xsl:template>
  
  <xsl:template match = "IntID"/>
  <xsl:template match = "TaxSort"/>
  <xsl:template match = "TEName"/>
</xsl:stylesheet>

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

MadeFrame 29.09.2023 21:00

У меня сейчас возникла одна проблема: если я скопирую файл &amp;lt;idref&amp;gt;PR001F&amp;lt;/idref&amp;gt; и поместите его в узел «Описание», а не в элемент списка, тогда он не преобразуется в узел, но когда он у меня есть в элементе списка, он преобразуется. Что мне там не хватает?

MadeFrame 29.09.2023 21:44

Добавлен полный xslt, который, вероятно, решит ваш измененный пример.

Siebe Jongebloed 01.10.2023 16:50

Другие вопросы по теме