Hi,
Sorry for taking this long to reply, I've been a little under the weather.
Here's a case, but it's important to note this is reproducable for EVERY xml
input longer than 1423 characters:
First, I've added XalanTransformToStream to XalanCAPI, as follows:
XALAN_TRANSFORMER_EXPORT_FUNCTION(int)
XalanTransformToStream(
istrstream *pTheXMLStream,
istrstream *pTheXSLStream,
XalanHandle theXalanHandle,
ostrstream *pTheOutput,
char *pszError,
int cbError)
{
int status = 0;
ostrstream theOutputStream;
XalanTransformer* const theTransformer =
getTransformer(theXalanHandle);
MemoryManager& theMemoryManager =
theTransformer->getMemoryManager();
status =
theTransformer->transform(pTheXMLStream, XSLTInputSource(pTheXSLStream,
theMemoryManager), *pTheOutput);
if (status != 0)
{
strncpy(pszError, theTransformer->getLastError(), cbError);
pszError[cbError] = '\0';
}
return status;
}
Then, I pass in streams generated from the following strings -
XML:
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<syslog>
<audit_record>
<Vendor>MyCompany</Vendor>
<Product>MyPrd</Product>
<Version>1.0.0000</Version>
<MessageID>100</MessageID>
<Desc>GenericDscString</Desc>
<Severity>Info</Severity>
<Issuer>user1</Issuer>
<Action>A Generic Action</Action>
<SourceUser></SourceUser>
<TargetUser></TargetUser>
<Safe>GenSafe</Safe>
<File>Root\bla.txt</File>
<Station>100.100.10.10</Station>
<Location></Location>
<Category></Category>
<RequestId>10</RequestId>
<Reason>1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
9012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345
67890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890</Reason>
<ExtraDetails></ExtraDetails>
<Message>A Generic Action</Message>
<GatewayStation></GatewayStation>
</audit_record>
</syslog>
XSL:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method='text' version='1.0' encoding='UTF-8'/>
<xsl:template match="/">
<xsl:for-each select="syslog/audit_record">CEF:0|
<xsl:value-of select="Vendor"/>|
<xsl:value-of select="Product"/>|
<xsl:value-of select="Version"/>|
<xsl:value-of select="MessageID"/>|
<xsl:choose><xsl:when test="Severity='Critical' or
Severity='Error'">Failure: </xsl:when></xsl:choose>
<xsl:call-template name="string-replace">
<xsl:with-param name="from" select="'='"/>
<xsl:with-param name="to" select="'\='"/>
<xsl:with-param name="string" select="Desc"/>
</xsl:call-template>|
<xsl:choose>
<xsl:when test="Severity='Critical'">10</xsl:when>
<xsl:when test="Severity='Error'">7</xsl:when>
<xsl:when test="Severity='Info'">5</xsl:when>
<xsl:otherwise>0</xsl:otherwise>
</xsl:choose>|act=
<xsl:call-template name="string-replace">
<xsl:with-param name="from" select="'='"/>
<xsl:with-param name="to" select="'\='"/>
<xsl:with-param name="string" select="Action"/>
</xsl:call-template> duser=
<xsl:call-template name="string-replace">
<xsl:with-param name="from" select="'='"/>
<xsl:with-param name="to" select="'\='"/>
<xsl:with-param name="string" select="Issuer"/>
</xsl:call-template> fname=
<xsl:call-template name="string-replace">
<xsl:with-param name="from" select="'='"/>
<xsl:with-param name="to" select="'\='"/>
<xsl:with-param name="string" select="File"/>
</xsl:call-template> src=
<xsl:call-template name="string-replace">
<xsl:with-param name="from" select="'='"/>
<xsl:with-param name="to" select="'\='"/>
<xsl:with-param name="string" select="Station"/>
</xsl:call-template> cs1Label="Affected User Name" cs1=
<xsl:call-template name="string-replace">
<xsl:with-param name="from" select="'='"/>
<xsl:with-param name="to" select="'\='"/>
<xsl:with-param name="string" select="SourceUser"/>
</xsl:call-template> cs2Label="Safe Name" cs2=
<xsl:call-template name="string-replace">
<xsl:with-param name="from" select="'='"/>
<xsl:with-param name="to" select="'\='"/>
<xsl:with-param name="string" select="Safe"/>
</xsl:call-template> cs3Label="Location" cs3=
<xsl:call-template name="string-replace">
<xsl:with-param name="from" select="'='"/>
<xsl:with-param name="to" select="'\='"/>
<xsl:with-param name="string" select="Location"/>
</xsl:call-template> cs4Label="Property Name" cs4=
<xsl:call-template name="string-replace">
<xsl:with-param name="from" select="'='"/>
<xsl:with-param name="to" select="'\='"/>
<xsl:with-param name="string" select="Category"/>
</xsl:call-template> cs5Label="Target User Name" cs5=
<xsl:call-template name="string-replace">
<xsl:with-param name="from" select="'='"/>
<xsl:with-param name="to" select="'\='"/>
<xsl:with-param name="string" select="TargetUser"/>
</xsl:call-template> cn1Label="Request Id" cn1=
<xsl:value-of select="RequestId"/> msg=
<xsl:call-template name="string-replace">
<xsl:with-param name="from" select="'='"/>
<xsl:with-param name="to" select="'\='"/>
<xsl:with-param name="string" select="Reason"/>
</xsl:call-template>,
<xsl:call-template name="string-replace">
<xsl:with-param name="from" select="'='"/>
<xsl:with-param name="to" select="'\='"/>
<xsl:with-param name="string" select="ExtraDetails"/>
</xsl:call-template>,
<xsl:choose><xsl:when test="Severity='Critical' or
Severity='Error'">Failure:</xsl:when></xsl:choose>
<xsl:call-template name="string-replace">
<xsl:with-param name="from" select="'='"/>
<xsl:with-param name="to" select="'\='"/>
<xsl:with-param name="string" select="Message"/>
</xsl:call-template>
</xsl:for-each>
</xsl:template>
<!-- replace all occurences of the character(s) `from' by the string `to' in
the string `string'.-->
<xsl:template name="string-replace">
<xsl:param name="string"/>
<xsl:param name="from"/>
<xsl:param name="to"/>
<xsl:choose>
<xsl:when test="contains($string,$from)">
<xsl:value-of select="substring-before($string,$from)"/>
<xsl:value-of select="$to"/>
<xsl:call-template name="string-replace">
<xsl:with-param name="string"
select="substring-after($string,$from)"/>
<xsl:with-param name="from" select="$from"/>
<xsl:with-param name="to" select="$to"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$string"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
The combination of these two values will result in the error in the subject.
Note that trimming the XML by removing as little as a single character from the
<Reason> string, will result in a perfectly fine result, so it's hard to
believe it's a case of stray bytes at the end of the stream.
The "similar" bug I came across was this (but it's not actually that similar at
all):
http://www.mail-archive.com/[email protected]/msg13497.html
Thanks for trying to help,
G.
--- On Thu, 2/25/10, David Bertoni <[email protected]> wrote:
From: David Bertoni <[email protected]>
Subject: Re: "invalid document structure" for XMLs longer than 1423 characters
To: [email protected]
Date: Thursday, February 25, 2010, 1:58 PM
On 2/25/2010 6:24 AM, Steven Gerrard wrote:
> Hi,
> I'm using Xalan-C 1.10 and Xerces-C 2.7, and have just encountered what
> seems to be a bug (or a misunderstanding on my part).
> Upgrading Xalan or Xerces is currently not an option due to time
> constraints.
> I'm using XalanTransformer::transform and pass an istrstream as an input
> XML.
> As long as my XML is upto 1423 characters, everything works like magic.
> Once I pass in an 1424 characters long XML, I get a -2 return code, and
> an "invalid document structure" error message.
> I looked around and saw a similar(?) bug that was first discovered in
> Xalan 1.4, but the fix seems to reflect the current state of my code,
> plus the bug itself was not reproducable in Xalan 1.3 so I imagine it
> was introduced in 1.4.
It's unlikely this is a bug in Xalan-C, since Xerces-C is reading the stream
and reporting the error. The usual reason for this are stray bytes at the end
of the stream, or a corrupted stream.
If you can come up with an isolated test case, including the input data, I can
take a look at what's going on.
Also, could you please post a reference to the the similar bug you found? It
would help me to take a look at the original bug report to see if there might
be a connection to your issue.
> Anyone encountered this issue, or can think of something I'm doing
> wrong? Even a way to workaround the issue would be greatly appreciated,
> as I'm pretty stumped here...
I would suggest you also test with ifstream and a disk file since the parser
will use the underlying istream interface to read the data.
Dave