abartsch Posted June 7, 2012 Share Posted June 7, 2012 Hi everybody, I'm new to XSLT and face a problem with cdata which is most probably a simple question for you. I have following XML input (which is mandatory): <table title="Installed Packages" separator="=" caption="true" appendix="false"> <![CDATA[Variant Name = APS]]> <![CDATA[b04hlr02a_VD = Z04Y5V641200]]> ...</table> I'd like to address each cdata line separately but I don't know how. The corresponding XSLT part looks like that: <xsl:when test="table[@title='Installed Packages']"> <tr id="trResultOK"> <td style="text-align:center"><xsl:value-of select="id"/></td> <td style="text-align:center"><xsl:value-of select="result"/></td> <td style="text-align:center"><xsl:value-of select="priority"/></td> <td><xsl:value-of select="text[@type='description']"/></td> <td><xsl:value-of select="table"/></td> </tr></xsl:when> As you can see, for now I address the table element just as a whole but I'd like to have each cdata block separately i.e. every cdata should be one line in the HTML document ending with a newline. Or with other words the table data should have separate lines for each single cdata block. The HTML could look like following: <td> Variant Name = APS<br /> b04hlr02a_VD = Z04Y5V641200<br /> ...</td> I'd be very thankful for any help. Link to comment Share on other sites More sharing options...
boen_robot Posted June 7, 2012 Share Posted June 7, 2012 Are you using an XSLT 1.0 processor or an XSLT 2.0 processor?This is not possible with XSLT 1.0 for sure... I'm not entirely positive about XSLT 2.0. Link to comment Share on other sites More sharing options...
abartsch Posted June 7, 2012 Author Share Posted June 7, 2012 So far I'm using version 1.0 but 2.0 could also be possible to be implemented. Link to comment Share on other sites More sharing options...
abartsch Posted June 7, 2012 Author Share Posted June 7, 2012 In case one cannot address cdata separately using XPATH neither with XSLT 1.0 nor with 2.0 maybe you have an idea to modify the cdata within a template. I already tried XSL function like substring-before and substring-after but this does not work for me. PS: Within Perl I would implement a pattern match for "string = string" but how to do this using XSL? Link to comment Share on other sites More sharing options...
Martin Honnen Posted June 7, 2012 Share Posted June 7, 2012 Sorry, but XSLT is not the right tool to deal with CDATA sections as the XSLT/XPath/XQuery data model does not know any CDATA sections so the stylesheet operates on a tree model with a single text node where the original markup in the source document has adjacent text and/or CDATA sections.If you need to manipulate CDATA section then you need a different data model and API, like DOM or like LINQ to XML. Link to comment Share on other sites More sharing options...
abartsch Posted June 8, 2012 Author Share Posted June 8, 2012 I'm calling the XSLT processor using PHP. Maybe, I have some possibilities to manipulate cdata in within PHP call? Here comes the code snipet: $xml = new DOMDocument;$xml->load("xml/$hostname.log.xml");$xsl = new DOMDocument;$xsl->load("xml/results.xsl");$proc = new XSLTProcessor;$proc->importStyleSheet($xsl);print(trim($proc->transformToXML($xml))); Thanks so far! Link to comment Share on other sites More sharing options...
Martin Honnen Posted June 8, 2012 Share Posted June 8, 2012 PHP's DOM implementation has http://www.php.net/manual/en/class.domcdatasection.php so with the DOM you should be able to find and distinguish CDATA section nodes. So pseudo code (sorry, I don't code with PHP) would be e.g. $table = $xml->getElementsByTagName("table")->item(0); for ($i = $table->childNodes->length - 1; i >= 0; i--) { $child = $table->childNodes->item(i); if ($child->nodeType == [b]XML_CDATA_SECTION_NODE) {[/b] $cdataWrapper = $xml->createElement("wrapper"); $cdataWrapper->textContent = $child->nodeValue; $child->parentNode->replaceChild($cdataWrapper, $child); } } Then in your stylesheet code you could match on e.g. table/wrapper. Link to comment Share on other sites More sharing options...
abartsch Posted June 8, 2012 Author Share Posted June 8, 2012 Thanks, Martin! I'll try to check this out but it can take a while since I'm a beginner in PHP, too ;-) Link to comment Share on other sites More sharing options...
abartsch Posted June 12, 2012 Author Share Posted June 12, 2012 Based on Martin's idea I could solve my problem: $xml = new DOMDocument; $xml->formatOutput = true; $xml->load("xml/$hostname.log.xml"); $elements = $xml->getElementsByTagName("*"); foreach($elements as $element) { foreach($element->childNodes as $item) { if( $item->nodeType == 4 ) // XML_CDATA_SECTION_NODE { $cdataWrapper = $xml->createElement("wrapper", $item->nodeValue); $element->parentNode->appendChild($cdataWrapper); // $item->parentNode->replaceChild($cdataWrapper, $item); } } } $xsl = new DOMDocument; $xsl->load("xml/wrapper.xsl"); $proc = new XSLTProcessor; $proc->importStyleSheet($xsl); print(trim($proc->transformToXML($xml))); Unfortunately, the replaceChild method did not work for me but I guess it's because I need the for-loop starting with the last cdata block as proposed by Martin. Anyway, this code adds XML wrapper tags for each cdata block separately which I can address via XSLT: <xsl:when test="wrapper"> <td><xsl:for-each select="wrapper"> <xsl:value-of select="." /><br /> </xsl:for-each></td> </xsl:when> Thanks to all who were supporting me! Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now