Вывод преобразования `>` вместо `>`

#xml #xslt #xpath

#xml #xslt #xpath

Вопрос:

Спасибо за вашу помощь! Я действительно ценю это! Я понимаю, почему мне нужно помещать значения в узлы, но я работаю не с шаблонами, а с функциями… Я просто не могу понять, как поместить эти узлы и шаблоны в функцию?

Может быть, будет проще, если я просто покажу свой файл XSLT. ниже вы можете найти файл, и, допустим, например, это может быть строка $, которую он передает функции (из не преобразованного XML-файла):

 amp;amp;#x003C;img src=amp;quot;Afbeeldingen Hotpot/beer.jpgamp;quot; alt=amp;quot;afbeelding van een beeramp;quot; title=amp;quot;beeramp;quot; width=amp;quot;170amp;quot; height=amp;quot;144amp;quot; style=amp;quot;display:block; margin-left:auto; margin-right:auto; text-align:center;amp;quot; style=amp;quot;float:center;amp;quot; /amp;amp;#x003E;
  

Это полное содержимое файла XSLT:

 <?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"     xmlns:foo="http://www.wathever.com"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs functx"
xmlns:functx="http://www.functx.com">

<xsl:import href="alle-functx-functies.xsl"/>

<xsl:function name="foo:functionIfImage">
    <xsl:param name="string" as="xs:string"/>
        <xsl:if test="contains($string,'.jpg')">
            <xsl:sequence select="foo:functionImage($string,'.jpg')"/>
        </xsl:if>
        <xsl:if test="contains($string,'.png')">
            <xsl:sequence select="foo:functionImage($string,'.png')"/>
        </xsl:if>
        <xsl:if test="contains($string,'.gif')">
            <xsl:sequence select="foo:functionImage($string,'.png')"/>
        </xsl:if>
        <xsl:if test="not(contains($string,'.jpg')) and not(contains($string,'.png')) and not(contains($string,'.gif'))">
            <xsl:sequence select="'iumi ondersteund alleen afbeeldingen van het formaat *.jpg, *.png of *.gif'"/>
        </xsl:if>
        <xsl:if test="not(contains($string,'img src='))">
            <xsl:sequence select="'bevat geen img src='"/>
        </xsl:if>

</xsl:function>
<xsl:function name="foo:functionImage">
    <xsl:param name="string" as="xs:string"/>
    <xsl:param name="type" as="xs:string"/>

    <xsl:variable name="quot">amp;quot;</xsl:variable>
    <xsl:variable name="beforePath" as="xs:string">img src="</xsl:variable>
    <xsl:variable name="globalPath" as="xs:string" select="substring-before(substring-after($string, $beforePath), $quot)" />
        <xsl:variable name="beforeWidth" as="xs:string">width="</xsl:variable>
        <xsl:variable name="width" as="xs:string" select="substring-before(substring-after($string, $beforeWidth), $quot)" />
            <xsl:variable name="beforeHeight" as="xs:string">height="</xsl:variable>
            <xsl:variable name="height" as="xs:string" select="substring-before(substring-after($string, $beforeHeight), $quot)" />

    <xsl:if test="not(contains($globalPath,'http'))">
        <xsl:variable name="fileName" as="xs:string"><xsl:sequence select="functx:substring-after-last($globalPath,'/')"/></xsl:variable>
        <xsl:variable name="compatibleData" as="xs:string">
            <xsl:sequence select="concat('amp;<img source=amp;quot;images/',$fileName,'amp;quot;',' width=amp;quot;',$width,'amp;quot; height=amp;quot;',$height,'amp;quot; /amp;>')"/>
        </xsl:variable>
        <xsl:value-of disable-output-escaping= "yes" select="$compatibleData" />
    </xsl:if>
    <xsl:if test="contains($globalPath,'http')">
        <xsl:variable name="compatibleData" as="xs:string">
            <xsl:sequence select="concat('amp;<img source=amp;quot;',$globalPath,'amp;quot;',' width=amp;quot;',$width,'amp;quot; height=amp;quot;',$height,'amp;quot; /amp;>')"/>
        </xsl:variable>
        <xsl:value-of disable-output-escaping= "yes" select="$compatibleData" />
    </xsl:if>

</xsl:function>
</xsl:stylesheet>
  

Итак, этот фрагмент моего XSLT-кода выдает неправильный вывод:

 <xsl:variable name="compatibleData" as="xs:string">
            <xsl:sequence select="concat('amp;<img source=amp;quot;',$globalPath,'amp;quot;',' width=amp;quot;',$width,'amp;quot; height=amp;quot;',$height,'amp;quot; /amp;>')"/>
</xsl:variable>
<xsl:value-of disable-output-escaping= "yes" select="$compatibleData" />
  

Вывод после преобразования:

 amp;<img source="images/beer.jpg" width="300" height="300" /amp;>
  

Вывод, который я хочу после преобразования:

 <img source="images/beer.jpg" width="300" height="300" />
  

Как я могу заставить вывод говорить < вместо amp;< и > вместо amp;> ?
значение-из disable-output-escaping= «yes» не работает…

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

1. Хороший вопрос, 1. Смотрите мой ответ для самого короткого, простого и наиболее понятного / поддерживаемого решения 🙂

Ответ №1:

Мой XSLT-код:

 <xsl:variable name="compatibleData" as="xs:string"><xsl:sequence select="concat('amp;<img source=amp;quot;images/',$fileName,'amp;quot;',' width=amp;quot;',$width,'amp;quot; height=amp;quot;',$height,'amp;quot; /amp;>')"/></xsl:variable>
   <xsl:sequence select="$compatibleData"/> 
  

Никогда не уничтожайте разметку, экранируя ее!!!

Всякий раз, когда XSLT используется для генерации XML-документа, он выводит элемент (и другие типы), узлы, а не строки.

Использовать:

 <img source="images/{$filename}" width="{$width}" height="{$height}" /> 
  

Объяснение: Использование AVT (Шаблоны атрибутов-значений) делает код короче и более читаемым. Всегда используйте AVTS, когда имена элементов и атрибутов известны заранее.

Ответ №2:

Вы пытаетесь вывести фактический структурированный (неэкранированный) XML, поэтому вам необходимо либо

  • предоставьте данные в XSLT в виде структурированного XML (как сказал @Jeff Swensen), или
  • предоставьте данные в XSLT в виде экранированного XML (как вы делаете), а затем отключите экранирование при выводе (как сказал @rsp). Это последнее считается грязным способом заставить XSLT делать то, что вы хотите, без реального понимания того, что происходит; и это может не сработать, в зависимости от вашего процессора XSLT и того, что управляет сериализацией.

Ответ №3:

На самом деле вы можете просто ввести <br/> в свой XSLT, и он перейдет в результат.

 <MyElement>
  <xsl:value-of select="/My/Element/Value"/>
  <br/>
</MyElement>
  

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

1. Хм, я не понимаю. Итак, я должен поместить <br/> в элемент или узел? На самом деле это был упрощенный код, я отредактировал свой вопрос… является ли ответ таким же?

Ответ №4:

Почему вы пытаетесь создать переменную с определением тега как xs:string ? Легко определить переменную с помощью element и использовать ее:

 <xsl:variable name="compatibleData">
    <img source="images/{$filename}" width="{$width}" height="{$height}"/>
</xsl:variable>

<xsl:template match="something">
    <xsl:copy-of select="$compatibleData"/>
</xsl:template>
  

Ответ №5:

Вот еще один вариант, для случая, когда вы не можете использовать значение-of без отключения вывода-экранирования (т. Е. в сочетании с copy-of):

 <xsl:stylesheet...>
  <xsl:output use-character-maps="special-chars"/>
  <xsl:character-map name="special-chars">
    <xsl:output-character character=">" string="amp;>"/>
  </xsl:character-map>
  

Ответ №6:

Я думаю, вы, возможно, ищете:

 <xsl:value-of disable-output-escaping= "yes" select="$compatibleData" />
  

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

1. @Dimitre, 1) возможно, вы захотите прочитать «Ест, стреляет и оставляет» 2) не опускайте допустимые альтернативы в соответствии с вашими симпатиями и антипатиями.

2. Значение ответа не может быть изменено чьими-либо отрицательными отзывами, симпатиями или антипатиями. Смотрите ответ @LarsH о недостатках предлагаемого вами решения. Самым большим недостатком является не только то, что это противоречит архитектуре модели обработки XSLT, но и то, что DOE не является обязательной функцией XSLT, и нет гарантии, что конкретный процессор XSLT вообще ее поддерживает. Насколько я знаю, процессор XSLT, используемый FF, не поддерживает DOE. Исходя из этого, любое отклонение от ответа DOE является обоснованным.