简体   繁体   中英

XSLT value-of issue then value contains xml

I have input data:

<?xml version="1.0" encoding="UTF-8"?>
 <?xml-stylesheet type="text/xsl" href="transform.xsl"?>
  <objects>
   <object>
    <properties>
     <property>
      <label>This is a label. Label contains <reference ref="#">references</reference> in random <reference ref="#">places</reference></label>
     </property>
    </properties>
   </object>
   <object/>
 </objects>

and transformation file:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
 <xsl:output method="html" version="1.0" encoding="UTF-8"/>
  <xsl:template match="/">
   <html>
    <body>
     <xsl:for-each select="//objects/object">
      <xsl:for-each select="properties/property">
       <xsl:value-of select="label"/>
       <xsl:for-each select="label/reference">
        <a href="{@ref}"><xsl:value-of select="."/></a>
       </xsl:for-each>
       <br/>
      </xsl:for-each>
     </xsl:for-each>
    </body>
   </html>
  </xsl:template>
 </xsl:stylesheet>

Expected result is:

This is a label. Label contains references in random places

but I'm getting:

This is a label. Label contains references in random places references places

How to solve that issue?

In your for-each iterating over properties/property you are outputting the reference-elements after the label-text-node. Instead iterate over all node()'s and choose between node-types:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
 <xsl:output method="html" version="1.0" encoding="UTF-8"/>
  <xsl:template match="/">
   <xsl:element name="html">
    <xsl:element name="body">
     <xsl:for-each select="//objects/object">
      <xsl:for-each select="properties/property">
       <xsl:for-each select="label/node()">
        <xsl:choose>
         <xsl:when test="self::text()">
          <xsl:value-of select="." />
         </xsl:when>
         <xsl:when test="local-name() = 'reference'">
          <a href="{@ref}"><xsl:value-of select="." /></a>
         </xsl:when>
        </xsl:choose>
       </xsl:for-each>
       <xsl:element name="br" />
      </xsl:for-each>
     </xsl:for-each>
    </xsl:element>
   </xsl:element>
  </xsl:template>
 </xsl:stylesheet>

This is a classic case where you should be using template rules rather than for-each. Replace your outermost for-each with <xsl:apply-templates select="//objects"/> and then do

<xsl:template match="label/reference">
   <a href="{@ref}"><xsl:value-of select="."/></a>
</xsl:template>

That's all you need: everything else is taken care of by the default template rules.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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