#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.