You are viewing a plain text version of this content. The canonical link for it is here.
Posted to c-users@xalan.apache.org by Karaki Kenichi <kk...@hotmail.com> on 2007/02/02 21:37:18 UTC

How to get wchar_t* from XSLTResultTarget, and ID transformation using Xalan?

Hi, everyone!

I'm a new Xalan-C user and not familiar with C++.

I want to get wchar_t* from XSLTResultTarget of 
XalanTransformer.transform() 
in order to pass the pointer to other vendor library for creating the 
vendor original
string object. So I have to write the XalanTransformer output to memory 
buffer.
The string creating function of that library accept wchar_t* to create 
Unicode
(UTF-16) string.
And I described "xsl:output encoding='UTF-16'" at my stylesheet.

I tried the following code, but it didn't work well.
My platform is IA32, OS is Windows XP Pro and IDE is Visual Studio 2003.

Please tell me some advices for my questions.


1. What kind of stream should I use to get output and pass the pointer 
easily?

  A. Tried using ostringstream
    Transform done fine, but I can't get wcha_t*.
    I observed the memory, and write fine. But I can't get string using 
str()
    because the memory buffer include null byte(0x00). And I don't know
    how to get the memory buffer pointer directly, maybe it's a problem
    of my C++ skills...
    But if this is better way, please tell me how to get the buffer 
pointer.

  B. Tried using wostirngstream
    transform() returns 0(success), but the memory buffer was
    0xff 0xfe 0x00 0x00 0x3c 0x00 0x3f 0x00 ...
    I don't know why null code inserted after BOM.

 C. Tried using XalanDOMString and PrintWriter
    because XSLTResultTarget accept Writer class object.
    But, when I executed transform(), I encounterd the assertion
    "npos == 0 | ..."
    What's wrong? Not enough initializing?


[Snippet code] 
  // Xerces and Xalan initialization

  // XSLTInputSource source
  // XSLTInputSource stylesheet (xsl:output encoding='UTF-16')

(A. Tried using ostringstream)
  ostringstream resultBuf;
  XSLTResultTarget result(resultBuf);

(B. Tried using wostringstream)
  wostringstream resultBufW;
  XSLTResultTarget result((XSLTResultTarget::StreamType&)resultBufW);

(C. Tried using XalanDOMString and PrintWriter)
  XalanDOMString domStr;
  DOMStringPrintWriter domSPW(domStr);
  XSLTResultTarget result(&domSPW);

  XalanTransformer transformer;
  int theResult = -1;
  theResult = transformer.transform(source, stylesheet, result);

  // Xalan and Xerces termination


2. Above code is a part of a porting from Java identity transformation
  such like following:

something.java
  import javax.xml.transform.Result;
  import javax.xml.transform.Source;
  import javax.xml.transform.Transformer;

  public void doTransform(Source source, Result result)
        throws TransformerException {
    TransformerFactory factory = createTransformerFactory();
    Transformer transfomer = factory.newTransformer();  // <- Create ID 
transformer
    transfomer.transform(source, result);
  }


 I ported this code to following C++ code. Is it correct? or Is there other 
better way?

#define IDENTITY_TRANSFORM_XSLT "<?xml version='1.0'?>\
<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' 
version='1.0'>\
<xsl:output encoding='UTF-16' />\
<xsl:template match='/'>\
<xsl:copy-of select='*' />\
</xsl:template>\
</xsl:stylesheet>"

int _tmain(int argc, _TCHAR* argv[])
{
  XMLPlatformUtils::Initialize();
  XalanTransformer::initialize();
  {
    (something code)

    XSLTInputSource inputSource( ** some input source **);

    const char* const  theStylesheet = IDENTITY_TRANSFORM_XSLT;
    istringstream theXSLStream(theStylesheet);
    const XSLTInputSource stylesheet(&theXSLStream);

    XSLTResultTarget result(resultBuf);

    XalanTransformer transformer;
    int theResult = -1;
    theResult = transformer.transform(parsedSource, stylesheet, result);

    (something code)
  }
}


I'm sorry a very long question, and sorry I'm not good at English.

Thank you.

Ken

_________________________________________________________________
Windows Vista の店頭販売開始!世界が変わる瞬間を体験しよう 
http://www.microsoft.com/japan/ultimatetimes/ 


Re: How to get wchar_t* from XSLTResultTarget, and ID transformation using Xalan?

Posted by David Bertoni <db...@apache.org>.
Karaki Kenichi wrote:
> Hi, Dave.
> 
> Thank you for your answering, and sorry about my incomplete assertion
> message.
> 
> Ok. I'd like to get high performance, so I give up using 
> std::ostringstream.
> And Should not I use std::ostrstream too?
> 
>> From: David Bertoni <db...@apache.org>
>>
>> > C. Tried using XalanDOMString and PrintWriter
>> >    because XSLTResultTarget accept Writer class object.
>> >    But, when I executed transform(), I encounterd the assertion
>> >    "npos == 0 | ..."
>> >    What's wrong? Not enough initializing?
>> >
>>
>> Well, you provided an incomplete assertion, and didn't bother to include
>> the file and line information, so it's impossible to say what went wrong.
>> There are no "levels" of initialization, so, if you've initialized both
>> Xerces-C and Xalan-C properly, it's not an issue of initialization.
> 
> I initialize Xerces-C and Xalan-C to use following two line only:
> XMLPlatformUtils::Initialize();
> XalanTransformer::initialize();
> 
> Is it not enough using XalanDOMString?

Yes, it's enough.

> 
> 
>> > (C. Tried using XalanDOMString and PrintWriter)
>> >  XalanDOMString domStr;
>> >  DOMStringPrintWriter domSPW(domStr);
>> >  XSLTResultTarget result(&domSPW);
>> >
>> >  XalanTransformer transformer;
>> >  int theResult = -1;
>> >  theResult = transformer.transform(source, stylesheet, result);
>>
>> This one should work, and that fact that you're getting an assert means
>> there's probably a bug in Xalan-C, but it's hard to say without seeing 
>> the
>> rest of the assert.
> 
> I'm using pre-build Xalan-C 1.10 and Xerces-C 2.7 for win32.
> Assertion message is following:
> 
> Title: Microsoft Visual C++ Runtime Library
> Assertion failed!
> Program: ....\testXML.exe
> File: C:\BuildClient\xalanc_roo\xalan-c_1_10_0-win32-m....
>  (message abbreviated by Runtime Library)
> Line: 114
> Expression: theLength == npos || lenght(s) >= theOffset + theLength
> 
> and when ignore the assertion, then encounterd following assertion:
> File: C:\BuildClient\xalanc_roo\xalan-c_1_10_0-win32-m....
>  (message abbreviated by Runtime Library)
> Line: 470
> Expression: thePosition < theSource.length() && (theCount == 
> size_type(npos)
>  || thePosition + theCount <=theSource.length())
> 
> I 'greped' by expression, and found that assertion at
> DOMStringPrintWriter.cpp:114 in write() function
> and XalanDOMString.hpp:470 in append() function.
> 

These are the result of a bug in Xalan-C.  You can see what was patched by
looking at the Jira issue:

https://issues.apache.org/jira/browse/XALANC-630

> 
>> This might not be the most efficient way of going this, depending on what
>> you'll do with the result.  For example, you could write a variation of
>> DOMStringPrintWriter that appends the "vendor string object" directly, 
>> but
>> I don't know what those APIs look like, so it's hard to say what might be
>> better.
> 
> I want to pass the result to SonicMQ C++ client library provided by 
> Sonic Software.
> That library provide following APIs for creating "vendor string object":
> StringRef createString(const wchar_t* c)
>    // StringRef is a wrapper class of a pointer to "vendor string 
> object", maybe..
> There are other APIs to create string object:
> StringRef createString(const char* c)  // for ASCII or MBCS
> StringRef createString(const unsigned char* c, const char* encoding) // 
> for UTF-8

If you're only working on Windows, then you can use the
DOMStringPrintWriter solution, as long as you apply the patch.  You can
then use XalanDOMString::c_str() to get a null-terminated pointer to the
UTF-16 data.  If your version of Visual C++ complains, you can cast this to
wchar_t.

If you want portability across multiple operating systems, you should
transform to UTF-8, then use the UTF-8 version of the createString() function.

Dave

Re: How to get wchar_t* from XSLTResultTarget, and ID transformation using Xalan?

Posted by Karaki Kenichi <kk...@hotmail.com>.
Hi, Dave.

Thank you for your answering, and sorry about my incomplete assertion
message.

Ok. I'd like to get high performance, so I give up using 
std::ostringstream.
And Should not I use std::ostrstream too?

>From: David Bertoni <db...@apache.org>
>
> > C. Tried using XalanDOMString and PrintWriter
> >    because XSLTResultTarget accept Writer class object.
> >    But, when I executed transform(), I encounterd the assertion
> >    "npos == 0 | ..."
> >    What's wrong? Not enough initializing?
> >
>
>Well, you provided an incomplete assertion, and didn't bother to include
>the file and line information, so it's impossible to say what went wrong.
>There are no "levels" of initialization, so, if you've initialized both
>Xerces-C and Xalan-C properly, it's not an issue of initialization.

I initialize Xerces-C and Xalan-C to use following two line only:
XMLPlatformUtils::Initialize();
XalanTransformer::initialize();

Is it not enough using XalanDOMString?


> > (C. Tried using XalanDOMString and PrintWriter)
> >  XalanDOMString domStr;
> >  DOMStringPrintWriter domSPW(domStr);
> >  XSLTResultTarget result(&domSPW);
> >
> >  XalanTransformer transformer;
> >  int theResult = -1;
> >  theResult = transformer.transform(source, stylesheet, result);
>
>This one should work, and that fact that you're getting an assert means
>there's probably a bug in Xalan-C, but it's hard to say without seeing the
>rest of the assert.

 I'm using pre-build Xalan-C 1.10 and Xerces-C 2.7 for win32.
 Assertion message is following:

Title: Microsoft Visual C++ Runtime Library
Assertion failed!
Program: ....\testXML.exe
File: C:\BuildClient\xalanc_roo\xalan-c_1_10_0-win32-m....
  (message abbreviated by Runtime Library)
Line: 114
Expression: theLength == npos || lenght(s) >= theOffset + theLength

and when ignore the assertion, then encounterd following assertion:
File: C:\BuildClient\xalanc_roo\xalan-c_1_10_0-win32-m....
  (message abbreviated by Runtime Library)
Line: 470
Expression: thePosition < theSource.length() && (theCount == 
size_type(npos)
  || thePosition + theCount <=theSource.length())

I 'greped' by expression, and found that assertion at
DOMStringPrintWriter.cpp:114 in write() function
and XalanDOMString.hpp:470 in append() function.


>This might not be the most efficient way of going this, depending on what
>you'll do with the result.  For example, you could write a variation of
>DOMStringPrintWriter that appends the "vendor string object" directly, but
>I don't know what those APIs look like, so it's hard to say what might be
>better.

I want to pass the result to SonicMQ C++ client library provided by Sonic 
Software.
That library provide following APIs for creating "vendor string object":
StringRef createString(const wchar_t* c)
    // StringRef is a wrapper class of a pointer to "vendor string object", 
maybe..
There are other APIs to create string object:
StringRef createString(const char* c)  // for ASCII or MBCS
StringRef createString(const unsigned char* c, const char* encoding) // for 
UTF-8

This C++ library is for accessing to Java Messaging System, so I think to 
handle strings
as Unicode(UTF-16) in my application because a string object in received 
message from
a system's broker is Unicode encoding, maybe.

Could you give me some more advice?

Thank you.

Ken

_________________________________________________________________
Hotmail に直接アクセス!MSN がさらに使いやすく http://jp.msn.com/ 


Re: How to get wchar_t* from XSLTResultTarget, and ID transformation using Xalan?

Posted by David Bertoni <db...@apache.org>.
Karaki Kenichi wrote:
> Hi, everyone!
> 
> I'm a new Xalan-C user and not familiar with C++.
> 
> I want to get wchar_t* from XSLTResultTarget of 
> XalanTransformer.transform() in order to pass the pointer to other 
> vendor library for creating the vendor original
> string object. So I have to write the XalanTransformer output to memory 
> buffer.

There is no standard way to get result in a wchar_t because wchar_t is not
very portable.  On some platforms, wchar_t is encoded in UTF-16, but on
others, it's encoded in UTF-32, or even something else.

> The string creating function of that library accept wchar_t* to create 
> Unicode
> (UTF-16) string.
> And I described "xsl:output encoding='UTF-16'" at my stylesheet.
> 
> I tried the following code, but it didn't work well.
> My platform is IA32, OS is Windows XP Pro and IDE is Visual Studio 2003.

If your only platform is Windows, then you can guarantee that wchar_t will
always be encoded in UTF-16, so you can simply
> 
> Please tell me some advices for my questions.
> 
> 
> 1. What kind of stream should I use to get output and pass the pointer 
> easily?
> 
>  A. Tried using ostringstream
>    Transform done fine, but I can't get wcha_t*.
>    I observed the memory, and write fine. But I can't get string using 
> str()
>    because the memory buffer include null byte(0x00). And I don't know
>    how to get the memory buffer pointer directly, maybe it's a problem
>    of my C++ skills...
>    But if this is better way, please tell me how to get the buffer pointer.

You shouldn't use std::ostringstream because the performance will be terrible.

> 
>  B. Tried using wostirngstream
>    transform() returns 0(success), but the memory buffer was
>    0xff 0xfe 0x00 0x00 0x3c 0x00 0x3f 0x00 ...
>    I don't know why null code inserted after BOM.
> 

You shouldn't use std::wostringstream either, because the performance will
be terrible, and unless you're doing the right thing, you'll get broken
results.  The result of a transformation is a stream of bytes, regardless
of what the encoding is, and wostringstream implements a string of wide
characters.

> C. Tried using XalanDOMString and PrintWriter
>    because XSLTResultTarget accept Writer class object.
>    But, when I executed transform(), I encounterd the assertion
>    "npos == 0 | ..."
>    What's wrong? Not enough initializing?
> 

Well, you provided an incomplete assertion, and didn't bother to include
the file and line information, so it's impossible to say what went wrong.
There are no "levels" of initialization, so, if you've initialized both
Xerces-C and Xalan-C properly, it's not an issue of initialization.

> 
> [Snippet code]  // Xerces and Xalan initialization
> 
>  // XSLTInputSource source
>  // XSLTInputSource stylesheet (xsl:output encoding='UTF-16')
> 
> (A. Tried using ostringstream)
>  ostringstream resultBuf;
>  XSLTResultTarget result(resultBuf);
> 
> (B. Tried using wostringstream)
>  wostringstream resultBufW;
>  XSLTResultTarget result((XSLTResultTarget::StreamType&)resultBufW);

Any time you are forced to use a C-style cast to get code to compile, you
can be assured you're doing something wrong.  XSLTResultTarget::StreamType
is a typedef for std::ostream, and std::wostringstream is not derived from
std::ostream.

> 
> (C. Tried using XalanDOMString and PrintWriter)
>  XalanDOMString domStr;
>  DOMStringPrintWriter domSPW(domStr);
>  XSLTResultTarget result(&domSPW);
> 
>  XalanTransformer transformer;
>  int theResult = -1;
>  theResult = transformer.transform(source, stylesheet, result);

This one should work, and that fact that you're getting an assert means
there's probably a bug in Xalan-C, but it's hard to say without seeing the
rest of the assert.

This might not be the most efficient way of going this, depending on what
you'll do with the result.  For example, you could write a variation of
DOMStringPrintWriter that appends the "vendor string object" directly, but
I don't know what those APIs look like, so it's hard to say what might be
better.

Dave