0
votes

I have an issue with xml/xsl files I have created (I have never worked with XML/XSLT before, so please excuse the quality).

I have been testing the XSLT transforms using IE, EDGE, Firefox and the MS XML Notepad. All nodes produce the correct output except the results_summary/text() node which has the following issue

When I run the XSLT transform in any browser the results_summary/text() node produces no output. When I run the same transform in the Microsoft XML Notepad it produces the correct output for that node.

My second issue is that all the browsers and the XML Notepad all produce the complete XML document at the end of the output document

The source XML was created by a different program I wrote. It converts an NBE structured file into an XML file

I have tested the XML file and it is well formed and valid

Any help would be greatly appreciated, apologies for the length of the code

Below is my XML file is

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="nbescan.xsl"?>
<scan xsi:noNamespaceSchemaLocation="nbescan.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<scan_start>Fri Apr 17 15:29:40 2020</scan_start>
    <host ip="10.10.10.10">
    <host_start>Fri Apr 17 15:29:51 2020</host_start>
        <results>
        <results_subnet>10.10.10</results_subnet>
        <results_ip>10.10.10.10</results_ip>
            <results_summary id="0000108323">
            <port>general/tcp</port>
            <results_severity>Log Message</results_severity>
                The script reports if:
                - a custom scan configuration is in use without having a Port scanner from
                the &apos;Port scanners&apos; family enabled.
                - a port scanner plugin was running into a timeout.
                - a required port scanner (e.g. nmap) is not installed.
                Vulnerability Detection Result:
                https://docs.greenbone.net/GSM-Manual/gos-6/en/performance.html#optimizing-the-scan-performance
                https://docs.greenbone.net/GSM-Manual/gos-6/en/scanning.html?highlight=scanner_plugins_timeout#preference-description
            </results_summary>
            <results_summary id="0000810002">
            <port>general/CPE-T</port>
            <results_severity>Log Message</results_severity>
                This routine uses information collected by other routines about
                CPE identities of operating systems, services and applications detected during the scan.
                Other:
                https://nvd.nist.gov/products/cpe
            </results_summary>
        </results>
    <host_end>Fri Apr 17 16:22:29 2020</host_end>
    </host>
<scan_end>Fri Apr 17 16:22:29 2020</scan_end>
</scan>

XSL File nbescan.xsl

<?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"/>
<xsl:template match="/">
    <table>
        <tr>
            <td></td>
            <td>Scan Started : </td>
            <td>
                <xsl:value-of select="scan/scan_start"/>
            </td>
            <td>Scan Finished : </td>
            <td>
                <xsl:value-of select="scan/scan_end"/>
            </td>
            <td></td>
        </tr>
    </table>
    <xsl:for-each select="scan/host">
    <table>
        <th>
            <td></td>
            <td></td>
            <td>Host</td>
            <td>
                <xsl:value-of select="@ip"/>
            </td>
            <td></td>
            <td></td>
        </th>
        <tr>
            <td></td>
            <td>Host Started : </td>
            <td>
                <xsl:value-of select="host_start"/>
            </td>
            <td>Host Finished : </td>
            <td>
                <xsl:value-of select="host_end"/>
            </td>
            <td></td>
        </tr>
    </table>

    <table>
        <tr>
            <td></td>
            <td>Results Host : </td>
            <td>
                <xsl:value-of select="results/results_ip"/>
            </td>
            <td>
                <xsl:value-of select="results/results_subnet"/>
            </td>
            <td></td>
        </tr>
    </table>
    <xsl:for-each select="results/results_summary">
    <table>
        <thead>
            <tr>
                <th>Results Summary</th>                
                <th>
                    <xsl:value-of select="@id"/>
                </th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td></td>
                <td>Port</td>
                <td><xsl:value-of select="port"/></td>
                <td>Severity</td>
                <td><xsl:value-of select="results_severity"/></td>
                <td></td>
            </tr>
        </tbody>
    </table>
    <div>
        <xsl:value-of select="text()"/>
    </div>
    <!-- results_sumary for each -->
    </xsl:for-each>
    <!-- host for each -->
    </xsl:for-each>
    <xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>

XSD File nbescan.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="results_summary">
        <xs:complexType mixed="true">
            <xs:sequence>
                <xs:element ref="port"/>
                <xs:element ref="results_severity"/>
            </xs:sequence>
            <xs:attribute name="id" type="xs:string" use="required"/>
        </xs:complexType>
    </xs:element>
    <xs:element name="port" type="xs:string"/>
    <xs:element name="scan">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="scan_start"/>
                <xs:element ref="host"/>
                <xs:element ref="scan_end"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="host">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="host_start"/>
                <xs:element ref="results"/>
                <xs:element ref="host_end"/>
            </xs:sequence>
            <xs:attribute name="ip" type="xs:string" use="required"/>
        </xs:complexType>
    </xs:element>
    <xs:element name="host_start" type="xs:string"/>
    <xs:element name="results_ip" type="xs:string"/>
    <xs:element name="scan_end" type="xs:string"/>
    <xs:element name="results_severity" type="xs:string"/>
    <xs:element name="scan_start" type="xs:string"/>
    <xs:element name="results">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="results_subnet"/>
                <xs:element ref="results_ip"/>
                <xs:element ref="results_summary" maxOccurs="unbounded"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="host_end" type="xs:string"/>
    <xs:element name="results_subnet" type="xs:string"/>
</xs:schema>
1
What do you consider the correct output? Perhaps you can reduce your samples to a minimum to demonstrate one problem. Doing <xsl:value-of select="text()"/> in XSLT 1 will output a text node with the contents of the first text child node of the context node which is pure white space in your sample, unless your tool by default strips white space. So perhaps you want to use <xsl:strip-space elements="*"/> if you expect the value-of output the first non-whitespace text node child. Or you use <xsl:apply-templates/> instead of the xsl:value-of.Martin Honnen
Then remove that trailing <xsl:apply-templates/> which would output any other text through the built-in templates.Martin Honnen
Thanks for the response Martin. The text node data in the XML file is not being output when using edge,firefox or ie, it is output only in the xml notepad editor. I resolved this issue by turning the text nodes into xml elements, and the browsers now output the test. I added an <summary-text> XML elementPeter De Óra
As a result I changed the <xsl:value-of select="text()"/> to <xsl:value-of select="."/>. I thought the XML standard stated that white space is preserved ? .I tested your <xsl:strip-space elements="*"/>, I changed it to <xsl:strip-space elements="summary_text"/> and that worked thank youPeter De Óra
I need to get my head around how text nodes work as distinct from elements and attributes, I obviously do not understand the distinction between white space and non white space in text nodes. My assumption was that the " The script reports if..." node is the first text node and that there would be no difference between the white and non white space characters contained therein.Peter De Óra

1 Answers

0
votes

To summarize the findings from the comments, the use of <xsl:apply-templates/> that you had at the end of your template processes all child nodes of the context node with the matching templates which in your case are the built-in ones which copy any text nodes to the result, so removing that <xsl:apply-templates/> should fix the problem of unwanted output.

For the text you want to output, in the XSLT/XPath data model, in the absence of a DTD or schema respectively with an XML parser like the ones in browsers which ignore schemas, any white space between elements results in text nodes with white space only; that way your results_summary element has as its first child node a text node with only white space, then the port element child. And in XSLT 1, using <xsl:value-of select="text()"/> outputs the first selected text child node in document order, so that is why you don't see any text output, that instruction outputs the white space before the port element. So there you need select="text()[normalize-space()]" or some better way using apply-templates to ensure that the text content you want to output is being output.

I can't really tell why you get different results in XML Notepad, it might use the schema to infer a content model but even then, at least in my understanding, as the schema defines a mixed content model, the first white space text node should not be ignored. Either XML Notepad, like many MS XML APIs, by default tries to strip white space, or its schema based parsing is different to what I would expect.