XSL - сделать все значения узлов с пространством имен доступными в разделах CDATA - PullRequest
0 голосов
/ 19 декабря 2018

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

Вход:

<note>
   <to>Tove</to>
   <from>Jani</from>
   <heading>Reminder</heading>
   <body>Don't forget me this weekend!</body>
</note>

Выход:

<note>
   <to><![CDATA[Tove]]></to>
   <from><![CDATA[Jani]]></from>
   <heading><![CDATA[Reminder]]></heading>
   <body><![CDATA[Don't forget me this weekend!]]></body>
</note>

1 Ответ

0 голосов
/ 19 декабря 2018

Этого можно добиться с помощью атрибута cdata-section-elements элемента xsl:output, который указывает все элементы, которые должны выводиться в секциях CDATA.

Поэтому используйте следующий XSLT-1.0:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="xml" version="1.0" cdata-section-elements="to from heading body" encoding="UTF-8" indent="yes" omit-xml-declaration="yes" />

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

</xsl:stylesheet>

Обратите внимание, что cdata-section-elements обозначает элементы to from heading body для включения их содержимого в раздел CDATA. шаблон идентификации просто копирует весь файл, относящийся к этому.


Если ваши элементы находятся в пространстве имен, вы должны поставить префикс имен элементов в cdata-section-elements с помощьюсоответствующий префикс пространства имен.

Например, если у вас есть следующий XML с пространством имен в корневом элементе, все дочерние узлы также находятся в этом пространстве имен.

<?xml version="1.0" encoding="utf-8"?>
<Bank xmlns="http://xxyy.x.com" Operation="Create">
  <Customer type="random">
    <CustomerId>Id10</CustomerId>
    <CountryCode>CountryCode19</CountryCode>
    <LanguageCode>LanguageCode20</LanguageCode>
    <AddressArray>
      <Address type="primary">
        <StreetAddress>179 Alfred St</StreetAddress>
        <City>Fortitude Valley</City>
        <County>GR</County>
        <Country>India</Country>
      </Address>
    </AddressArray>
  </Customer>
</Bank>

Используйте этоXSLT (обратите внимание на объявление пространства имен в элементе xsl:stylesheet):

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:ns0="http://xxyy.x.com">
  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" cdata-section-elements="ns0:CustomerId ns0:CountryCode ns0:LanguageCode ns0:StreetAddress ns0:City ns0:County ns0:Country" omit-xml-declaration="yes" />

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

</xsl:stylesheet>

Убедитесь, что пространство имен XSLT соответствует пространству имен XML, здесь оба значения http://xxyy.x.com, но в вашемДля примера XML это xxyy.x.com.


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

Если у вас есть большое количество элементов, вы можете добавить их все в cdata-section-elements(возможно, создавая его по другой таблице стилей) или используйте решение, которое я нашел здесь: Обтекание всех элементов в CDATA .Это своего рода хак.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"  omit-xml-declaration="yes" />

    <xsl:variable name="CDATABegin" select="'&lt;![CDATA['" />
    <xsl:variable name="CDATAEnd" select="']]&gt;'" />

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

    <xsl:template match="text()[normalize-space()]">
      <xsl:value-of select="$CDATABegin" disable-output-escaping="yes"/>
      <xsl:value-of select="." disable-output-escaping="yes"/>
      <xsl:value-of select="$CDATAEnd" disable-output-escaping="yes"/>
    </xsl:template>

</xsl:stylesheet>

Оборачивает все непустые узлы text() в разделах CDATA.Но и здесь вы должны упомянуть все элементы в правилах сопоставления шаблонов, содержащих код переноса CDATA.

Какой вариант будет проще применить, зависит от большего сценария.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...