jorgen
jorgen

Reputation: 1257

Read xml inside xml with xslt

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?

Upvotes: 1

Views: 4120

Answers (3)

Chris Scott
Chris Scott

Reputation: 1761

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.

Upvotes: 2

Tomalak
Tomalak

Reputation: 338208

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.

Upvotes: 0

Cerebrus
Cerebrus

Reputation: 25775

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) ?

Upvotes: 1

Related Questions