#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 является обоснованным.