[英]How do I serialize output from a node-set in xslt 1.0?
我正在使用 XSLT 中的一些 XML。 我想將它的一部分保存在內容節點中。 我在這個例子中沒有使用 CDATA 節點。
當我像這樣抓取 xml 時,它被轉義了,即。 <
= <
<content name="test”>
<xsl:copy-of select="//content[@name='something']/node()" />
</content>
但是在將數據存儲到內容節點之前,我需要對數據進行一些處理。 我有一個 xsl:for-each 調用,它循環保存部分。 但是,當我調用類似的命令時,我無法讓 XML 轉義。
<xsl:for-each select="exsl:node-set($xml)//data">
<content name="test">
<xsl:copy-of select="./node()" />
</content>
我已經在它周圍放置了 CDATA 節點並輸出了內容,但是我在系統中遇到了雙重轉義問題。 我真的需要這個調用副本來輸出轉義的 XML。
我真的想要這樣的東西:
<content name="test">
<data>Some data<\data>
</content>
輸入將是這樣的:
<root>
<data>Some data</data>
<data>more data</data>
</root>
這是數據的簡化。 數據節點中會有額外的 xml 節點。
Evan Lenz 在http://lenzconsulting.com/xml-to-string/有一個基於 XSLT 1 的 XML 序列化實現:如果你使用它,你有例如
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:import href="http://lenzconsulting.com/xml-to-string/xml-to-string.xsl"/>
<xsl:output indent="yes" cdata-section-elements="content"/>
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="data">
<content>
<xsl:apply-templates select="." mode="xml-to-string"/>
</content>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/pPzifpn/4
如果處理器是 libxslt,那么它可能允許您實現擴展功能,例如 PHP 允許您調用 PHP 函數,而 PHP 中的DOMDocument
有一個用於序列化的saveXML
函數,因此您可以從 XSLT 調用它:
<?php
function serializeNode($node) {
return $node[0]->ownerDocument->saveXML($node[0]);
}
$xml = <<<EOT
<root>
<data>Some data</data>
<data>more data</data>
</root>
EOT;
$xsl = <<<EOT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:php="http://php.net/xsl"
exclude-result-prefixes="php"
version="1.0">
<xsl:output indent="yes" cdata-section-elements="content"/>
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="data">
<content>
<xsl:value-of select="php:function('serializeNode', .)"/>
</content>
</xsl:template>
</xsl:stylesheet>
EOT;
$doc = new DOMDocument();
$doc->loadXML($xml);
$proc = new XSLTProcessor();
$proc->registerPHPFunctions('serializeNode');
$sheet = new DOMDocument();
$sheet->loadXML($xsl);
$proc->importStylesheet($sheet);
echo $proc->transformToXml($doc);
?>
<!-- XSL 1.0 -->
<xsl:template match="*|@*|text()|comment()" mode="copy">
<xsl:param name="_-"><!--<">-do-not-modify-this--></xsl:param>
<xsl:variable name="ch" select="document('')//*[@name='_-']/comment()"/>
<xsl:variable name="lt" select="substring($ch, 1, 1)"/>
<xsl:variable name="qq" select="substring($ch, 2, 1)"/>
<xsl:variable name="gt" select="substring($ch, 3, 1)"/>
<xsl:choose>
<xsl:when test="self::*">
<xsl:value-of select="concat($lt, name())"/>
<xsl:apply-templates select="@*" mode="copy"/>
<xsl:variable name="ns" select="namespace-uri()"/>
<xsl:if test="$ns and not(ancestor::*[namespace-uri() = $ns])">
<xsl:variable name="pf" select="substring-before(name(), ':')"/>
<xsl:value-of select="concat(' xmlns:', $pf, '=', $qq, $ns, $qq)"/>
</xsl:if>
<xsl:value-of select="$gt"/>
<xsl:apply-templates select="*|text()|comment()" mode="copy"/>
<xsl:value-of select="concat($lt, '/', name(), $gt)"/>
</xsl:when>
<xsl:when test="self::comment()">
<xsl:value-of select="concat($lt, '!--', ., '--', $gt)"/>
</xsl:when>
<xsl:when test="self::text()"><xsl:value-of select="."/></xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat(' ', name(), '=', $qq, ., $qq)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.