tags:

views:

397

answers:

3

I got this XML document with an XML-string defined inside an element:

<HIT>
<FIELD NAME="xmlstring">
&lt;?xml version="1.0"?&gt;
&lt;kontaktpersoner&gt;&lt;person&gt;&lt;funksjon&gt;&lt;![CDATA[Økonomi]]&gt;&lt;/funksjon&gt;&lt;tittel&gt;      &lt;![CDATA[regnskapsansv.]]&gt;&lt;/tittel&gt;&lt;email&gt;&lt;![CDATA[[email protected]]]&gt;&lt;/email&gt;&lt;navn&gt;&lt;![CDATA[Test Test]]&gt;&lt;/navn&gt;&lt;/person&gt;&lt;person&gt;&lt;funksjon&gt;&lt;![CDATA[Leder]]&gt;&lt;/funksjon&gt;&lt;tittel&gt;&lt;![CDATA[adm. dir.]]&gt;&lt;/tittel&gt;&lt;email&gt;&lt;![CDATA[[email protected]]]&gt;&lt;/email&gt;&lt;navn&gt;&lt;![CDATA[Test2 Test]]&gt;&lt;/navn&gt;&lt;/person&gt;&lt;/kontaktpersoner&gt;
</FIELD>
</HIT>

The XML inside the element with the "xmlstring" attribute is escaped with &lt; and &gt; and is read as string and not XML.

How do I make it possible to use this with XPath in XSLT?

+1  A: 

The XML inside the "xmlstring" attribute is escaped with &lt; and &gt; and is read as string and not XML.

Think about it... Isn't that precisely how things should be? How is your XSLT supposed to know that your XML contains XML within XML (and that nested XML is not even within a CDATA section) ?

Cerebrus
Well, actually, it's not XML at all.
John Saunders
@John: Actually, it *represents* an XML string. I think you misunderstand the OP's question.
Cerebrus
A: 

I don't think this can be done in a one-step process in XSLT.

Your only chance is to extract the document string, parse it into a separate XML document, and take it from there.

As an alternative solution, you cold write a transformation like this:

<xsl:stylesheet 
  version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*" />
    </xsl:copy>
  </xsl:template>

  <xsl:template match="FIELD[@NAME='xmlstring']">
    <xsl:copy>
      <xsl:copy-of select="@*" />

      <!-- now this is somewhat brittle, I would not really recommend 
           it for production use, but maybe it helps nevertheless -->
      <xsl:choose>
        <xsl:when test="contains(., '&lt;?xml')">
          <xsl:value-of select="substring-after(., '?&gt;')" disable-output-escaping="yes" />
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="." disable-output-escaping="yes" />
        </xsl:otherwise>
      </xsl:choose>

    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

which produces:

<HIT>
  <FIELD NAME="xmlstring">
    <kontaktpersoner>
      <person>
        <funksjon><![CDATA[Økonomi]]></funksjon>
        <tittel><![CDATA[regnskapsansv.]]></tittel>
        <email><![CDATA[[email protected]]]></email>
        <navn><![CDATA[Test Test]]></navn>
      </person>
      <person>
        <funksjon><![CDATA[Leder]]></funksjon>
        <tittel><![CDATA[adm. dir.]]></tittel>
        <email><![CDATA[[email protected]]]></email>
        <navn><![CDATA[Test2 Test]]></navn>
      </person>
    </kontaktpersoner>
  </FIELD>
</HIT>

Which then can be used like a normal XML document in a second step.

Tomalak
A: 

If you can switch xslt processors, Saxon has a parse function that would allow you use import the embedded document into a variable and process it like you would your input document.

16bytes