XSLT, измените некоторые теги с префиксом с lt / gt на , а некоторые все еще с lt / gt

#xml #xslt

#xml #xslt

Вопрос:

Может быть, некоторые помогут мне решить задачу 🙂 У меня есть входной xml, например:

 <n0:sendRequests xmlns:n0="http://upg.sbns.bssys.com/" xmlns:prx="urn:sap.com:proxy:DAX:/1SAI/TAS530E8C549ADDED8C7693:740">
    <n0:requests>amp;<upg:Request xmlns:upg="http://bssys.com/upg/request" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" requestId="55555555-5555-5555-5555-550000090095" version="1" sender="1" receiver="1"amp;>amp;<upg:Modelsamp;>amp;<upg:Modelamp;>amp;<StatementRequest xmlns="http://bssys.com/sbns/integration"amp;>amp;<docIdamp;>90095amp;</docIdamp;>amp;<docDateamp;>2020-09-10amp;</docDateamp;>amp;<docNumberamp;>90095amp;</docNumberamp;>amp;<orgIdamp;>6c74b51b-fb90-4270-8a1b-ae07177a8905amp;</orgIdamp;>amp;<orgInnamp;>7736050003amp;</orgInnamp;>amp;<orgNameamp;>JSC Companyamp;</orgNameamp;>amp;<fromDateamp;>2020-05-11amp;</fromDateamp;>amp;<toDateamp;>2020-05-11amp;</toDateamp;>amp;<accountsamp;> amp;<Accamp;>amp;<accountamp;>40702810500010000848amp;</accountamp;>amp;<bankBICamp;>044525220amp;</bankBICamp;>amp;<bankNameamp;>ABRamp;</bankNameamp;>amp;<orgNameamp;>JSC Companyamp;</orgNameamp;>amp;</Accamp;>amp;</accountsamp;>amp;<signCollectionamp;>amp;<SignCollectionamp;>amp;</SignCollectionamp;>amp;</signCollectionamp;>amp;</StatementRequestamp;>amp;</upg:Modelamp;>amp;</upg:Modelsamp;>amp;</upg:Requestamp;>
    </n0:requests>
    <n0:sessionId>0174774e-e79f-19d8-bf28-5e423cf0d53c</n0:sessionId>
</n0:sendRequests>
  

И у меня есть отображение xslt:

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
 xmlns:upg="http://upg.sbns.bssys.com/" xmlns:n0="http://upg.sbns.bssys.com/">
 <xsl:output method="xml" encoding="utf-8" omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

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

    <xsl:template match="n0:requests">
        <xsl:copy>
            <xsl:text disable-output-escaping="yes">amp;<![CDATA[ </xsl:text>
            <xsl:value-of select="." disable-output-escaping="yes"/>
            <xsl:text disable-output-escaping="yes">]]amp;></xsl:text>
        </xsl:copy>
</xsl:template>

</xsl:stylesheet>`
  

вывод должен быть:

   <n0:sendRequests>
    <n0:requests><![CDATA[
    <upg:Request requestId="13131313-0000-1111-2211-001111111111" version="1" sender="1" 
                 receiver="1" xmlns:upg="http://bssys.com/upg/request" 
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
     <upg:Models>
       <upg:Model>amp;<StatementRequest 
              xmlns=amp;quot;http://bssys.com/sbns/integrationamp;quot;amp;> 
        amp;<orgIdamp;>b14a6b8c-54ba-45af-8420-fdac775f6fe5amp;</orgIdamp;> 
        amp;<accountsamp;> 
                    amp;<Accamp;> 
                               amp;<accountamp;>40702810200000005400amp;</accountamp;> 
                               amp;<bankBICamp;>044030861amp;</bankBICamp;> 
                    amp;</Accamp;> 
        amp;</accountsamp;> 
        amp;<docDateamp;>2020-09-08amp;</docDateamp;> 
        amp;<docIdamp;>13131312-1fe4-11ea-9220-000c29bc93aaamp;</docIdamp;> 
        amp;<docNumberamp;>133amp;</docNumberamp;> 
        amp;<fromDateamp;>2020-09-01amp;</fromDateamp;> 
        amp;<orgInnamp;>7810356897amp;</orgInnamp;> 
        amp;<orgNameamp;>ЗАО  amp;quot;JSC Companyamp;quot;amp;</orgNameamp;> 
        amp;<toDateamp;>2020-09-02amp;</toDateamp;> 
        amp;<signCollectionamp;>
        amp;<SignCollection/amp;>
        amp;</signCollectionamp;>
        amp;</StatementRequestamp;> 
</upg:Model>
 </upg:Models>
</upg:Request>
 ]]></n0:requests>
     <n0:sessionId>01746e15-004e-14f5-b4e6-f6c8b357e000</n0:sessionId>
  </n0:sendRequests>
  

внутри тега n0: требуются запросы, заменяющие amp;lt/ amp;gt на <> для тегов с префиксом upg: и сохраните amp;lt /amp;gt для других тегов без префикса (пример

Теперь мой xslt заменяет все amp;lt / amp; gt на <> : ( Это действительно можно сделать на XSLT?

Ответ №1:

Не ясно, в чем заключается ваш вопрос. Ваша таблица стилей на самом деле ничего не делает. Экранированный XML семантически эквивалентен XML, содержащемуся в разделе CDATA. Вы могли бы достичь того же результата гораздо проще и элегантнее, выполнив всего:

 <xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:n0="http://upg.sbns.bssys.com/" >
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" cdata-section-elements="n0:requests"/>

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

</xsl:stylesheet>
  

Ожидаемый результат показывает раздел CDATA с экранированным некоторым содержимым XML, что не имеет никакого смысла.

В общем, когда у вас есть строка, представляющая XML — независимо от того, экранирована она или содержится в CDATA — и вы хотите внести изменения в XML-содержимое строки, лучше всего сначала преобразовать строку в XML, а затем обработать ее обычным способом с помощью XSLT. В противном случае вы ограничены манипулированием строками, что очень утомительно и подвержено ошибкам.

Комментарии:

1. Входное сообщение не содержит CDATA, я должен добавить его. Внутри CDATA я должен заменить amp;lt / $ gt на <> для тегов с префиксом upg: но этот текст содержит теги, например StatementRequest, и для этих тегов я должен остаться amp;lt.

2. Я не думаю, что вы понимаете, о чем я говорю. XML внутри CDATA — это то же самое, что и экранированный XML.. Вы говорите, что хотите экранировать XML внутри CDATA. Это был бы XML, который экранируется дважды , что не имеет смысла.

Ответ №2:

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

Обратите внимание, что ваш пример вывода, содержащий

 <upg:Model>amp;<StatementRequest 
              xmlns=amp;quot;http://bssys.com/sbns/integrationamp;quot;amp;>
...
amp;</StatementRequestamp;> 
</upg:Model>
  

представляет точно такое же дерево узлов, как

 <upg:Model><![CDATA[<StatementRequest 
              xmlns="http://bssys.com/sbns/integration">
...
</StatementRequest>]]>
</upg:Model>
  

Это просто разные сериализации одного и того же результирующего дерева, поэтому, насколько это касается XSLT, они идентичны.

С современным процессором XSLT (XSLT 3.0) вы можете построить такой результат, используя конструкцию типа:

 <upg:Model>
  <xsl:variable name="temp">
    <StatementRequest 
                  xmlns="http://bssys.com/sbns/integration">
      ...
    </StatementRequest>
  </xsl:variable>
  <xsl:value-of select="serialize($temp)"/>  
</upg:Model>
  

Но функция serialize() недоступна в более ранних версиях XSLT.