简体   繁体   English

如何序列化 xslt 1.0 中节点集的输出?

[英]How do I serialize output from a node-set in xslt 1.0?

I am working with some XML inside of XSLT.我正在使用 XSLT 中的一些 XML。 I want to save a section of it in a content node.我想将它的一部分保存在内容节点中。 I left the CDATA node out of this example.我在这个例子中没有使用 CDATA 节点。

When I grab the xml like this it's escaped ie.当我像这样抓取 xml 时,它被转义了,即。 &lt; = < = <

<content name="test”>
      <xsl:copy-of select="//content[@name='something']/node()" />
</content>

But I need to do some processing on the data before I store it in a content node.但是在将数据存储到内容节点之前,我需要对数据进行一些处理。 I have an xsl:for-each call and it loops saving sections.我有一个 xsl:for-each 调用,它循环保存部分。 However, when I call a similar command I can't get the XML to escape.但是,当我调用类似的命令时,我无法让 XML 转义。

<xsl:for-each select="exsl:node-set($xml)//data">
    <content name="test">
              <xsl:copy-of select="./node()" />
    </content>

I've put CDATA nodes around it and outputted the content, but then I have issues in the system with double escaping.我已经在它周围放置了 CDATA 节点并输出了内容,但是我在系统中遇到了双重转义问题。 I really need this copy-of call to output escaped XML.我真的需要这个调用副本来输出转义的 XML。

I really want something like:我真的想要这样的东西:

<content name="test">
          &lt;data&gt;Some data&lt;\data&gt;
        </content>

Input would be something like this:输入将是这样的:

<root>
<data>Some data</data>
<data>more data</data>
</root>

This a simplification of the data.这是数据的简化。 There would be additional xml nodes in the data node.数据节点中会有额外的 xml 节点。

Evan Lenz has an XSLT 1 based implementation of XML serialization at http://lenzconsulting.com/xml-to-string/ : if you use that you have eg 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 https://xsltfiddle.liberty-development.net/pPzifpn/4

If the processor is libxslt then it might allow you to implement an extension function, for instance PHP allows you to call PHP functions and the DOMDocument in PHP has a saveXML function to serialize, so you can call that from XSLT:如果处理器是 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM