Wrox Programmer Forums
Go Back   Wrox Programmer Forums > XML > XSLT
|
XSLT General questions and answers about XSLT. For issues strictly specific to the book XSLT 1.1 Programmers Reference, please post to that forum instead.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the XSLT section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
 
Old March 17th, 2011, 02:47 PM
Registered User
 
Join Date: Mar 2011
Posts: 8
Thanks: 0
Thanked 0 Times in 0 Posts
Default xml copy with text substitution from map

I am debugging some Soap XML msgs for WS development and I need to be
able to visually read it to understand whats happening. I have 2 problems:
1. Most of the XML is presented as escaped XML within one string element.
2. There are numerous elements that contain 32 Character Alpha-Numeric
UIDs.

I have a java Map that I created to substitute UIDs for readable Strings,
but I don't know how to do substitution and I am not sure where to start.
Also, I don't know which elements will need substitution, so I was thinking
I could just check the contents of each elements text and see if its in the
map, if yes then substitute.

If you could provide me with some hints/clues or something to search on
that would be great.

thanks in advance,
Tim

Here is what I have:
Code:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope 
        xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xmlns:xsd="http://www.w3.org/2001/XMLSchema">
	<soap:Body>
		<RetrieveListResponse xmlns="http://wsdl.somebody.com/Stuff/">
			<RetrieveListResult xmlns="">&lt;RETURNS&gt;&lt;STATUS&gt;A92A7EBEE897499fA8B06D5FE94B8A30&lt;/STATUS&gt; &lt;/RETURNS&gt;</RetrieveListResult>
		</RetrieveListResponse>
	</soap:Body>
</soap:Envelope>

After un-escaping the XML, I still have to convert the UIDs (example here
is <STATUS>) to something readable from my map.

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope 
        xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xmlns:xsd="http://www.w3.org/2001/XMLSchema">
	<soap:Body>
	  <RetrieveListResponse xmlns="http://wsdl.somebody.com/Stuff/">
             <RetrieveListResult xmlns="">
               <RETURNS>
                <STATUS>A78A7EBFF897499fA8206D5FE94B8A30</STATUS>
              </RETURNS>
            </RetrieveListResult>
	  </RetrieveListResponse>
	</soap:Body>

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope 
        xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xmlns:xsd="http://www.w3.org/2001/XMLSchema">
	<soap:Body>
	   <RetrieveListResponse xmlns="http://wsdl.somebody.com/Stuff/">
              <RetrieveListResult xmlns="">
                <RETURNS>
                    <STATUS>FAILURE</STATUS>
                </RETURNS>
              </RetrieveListResult>
	    </RetrieveListResponse>
	</soap:Body>
</soap:Envelope>
 
Old March 21st, 2011, 03:31 AM
Registered User
 
Join Date: Mar 2011
Posts: 8
Thanks: 0
Thanked 0 Times in 0 Posts
Default

I made a little bit of progress with the following but I don't know how to put
together.

I specify the exact element name that has the escaped Xml I can get it
to un-escape the xml, but it won't do the substitution and its also not
formatted. If I do the un-escape/formatting first and then run it again it will do the substitution.

Is there a way to do this all in one pass?

Code:
?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:guid="java:com.me.ConstantsMap">

  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
  </xsl:template>
  
   
   <xsl:template match="RetrieveListResult ">
    <xsl:value-of select="." disable-output-escaping="yes" />
   </xsl:template>

  <xsl:template match="*/text()" xmlns:guid="java:com.me.ConstantsMap">
    <xsl:value-of select="guid:getGUIDName(.)"/>
  </xsl:template>
</xsl:stylesheet>
 
Old March 21st, 2011, 05:29 AM
samjudson's Avatar
Friend of Wrox
 
Join Date: Aug 2007
Posts: 2,128
Thanks: 1
Thanked 189 Times in 188 Posts
Default

Your best bet would probably be to set the java function to take the un-escaped XML, and return the escaped XML with the substitution in place as well.

Either that or you'll need to use an extension method to parse the un-escaped XML into a node-set, and then process the node-set. How you do that would depend on the XSLT processor you are using.
__________________
/- Sam Judson : Wrox Technical Editor -/

Think before you post: What have you tried?
 
Old March 21st, 2011, 11:23 AM
Registered User
 
Join Date: Mar 2011
Posts: 8
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Thanks Sam I will give it a try.

Currently, I am using this transform via a Java program. I call the XSLT transform
via:

Code:
TransformerFactory factory = TransformerFactory.newInstance();

		StreamSource xslStream = new StreamSource(inXSL);
		Transformer transformer = factory.newTransformer(xslStream);
		transformer.setErrorListener(new MyErrorListener());

		StreamSource in = new StreamSource(inXML);
		StreamResult out = new StreamResult(outTXT);
		transformer.transform(in, out);
I didn't really have an idea about the correct approach to do this in the
first place, but now it seems I will be doing all of the processing in java.
Should I just drop the XSLT transform altogether and do some type of custom
SAX Parser (ala Java and XSLT, ch5)? This is my first time using XSLT and
I am still trying to figure out how and when and where to use it correctly.
 
Old March 22nd, 2011, 03:21 AM
samjudson's Avatar
Friend of Wrox
 
Join Date: Aug 2007
Posts: 2,128
Thanks: 1
Thanked 189 Times in 188 Posts
Default

Actually, I meant modify your 'map' function, so that it converted the text of the RetrieveListResult into a XML fragment, then did the replacement and returned the entire XML fragment.

If you are using Saxon then you could just use the saxon:parse method instead however.

Code:
<xsl:template match="RetrieveListResult ">
    <xsl:copy>
        <xsl:apply-templates select="saxon:parse(.)"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="STATUS" xmlns:guid="java:com.me.ConstantsMap">
    <xsl:copy><xsl:value-of select="guid:getGUIDName(.)"/></xsl:copy>
</xsl:template>
It is also possible, that if you could maintain the list of mappings in an XML file, then you could use XSLT to do the mapping as well, but that is up to you.
__________________
/- Sam Judson : Wrox Technical Editor -/

Think before you post: What have you tried?
 
Old March 23rd, 2011, 03:12 PM
Registered User
 
Join Date: Mar 2011
Posts: 8
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Sam,

Thanks for the update. Since I am creating the map via a java program and
the data is somewhat static I could easily output it in XML format, but I am
not sure what format to use nor how to use the mapped XML. I need to take
a look at this and the saxon.parse().

Tim
 
Old March 26th, 2011, 06:27 PM
Registered User
 
Join Date: Mar 2011
Posts: 8
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Sam,

the saxon:parse() is the definitely what I wanted to use for CDATA and
escaped xml.

My Request Soap/XML has a fixed element <sXmlParameters> and the
xsl below works great for it. But my response XML is not the same
for every msg. The only thing I do know is that the elment ends-with
Result, e.g. <RetrieveListResult>, <RetrieveResult>, or <XyzResult>.

I tried using fn:ends-with(., 'Result')" in the match pattern but that
throws a XTSE0340: XSLT Pattern syntax error. Is there a way for
me to wildcard a pattern?

If I can this going my next step is to follow up on you other suggestion,
to keep a list of mappings in the xsl file. That would be great because
then I could just run it from within eclipse, without the need for my
transform.java program.

THanks!
Tim


Code:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
   xmlns:saxon="http://saxon.sf.net/"
   xmlns:guid="java:com.emeter.pipe.dca.echelon.ConstantsMap"
  exclude-result-prefixes="saxon guid"
>

  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
  </xsl:template>

  <xsl:template match="sXmlParameters" >
  <sXmlParameters>
    <xsl:apply-templates select="saxon:parse(.)" />
    </sXmlParameters>
  </xsl:template>

  <!-- 
     This does not work, can't use functions here
    <xsl:template match="fn:ends-with(., 'Result')" mode="process-Rsp-message">
    <xsl:apply-templates select="saxon:parse(.)" mode="process-response-payload" />
  </xsl:template>
   -->

    <xsl:template match="*/text()" xmlns:guid="java:com.emeter.pipe.dca.echelon.ConstantsMap" >
    <xsl:value-of select="guid:getGUIDName(.)" />
  </xsl:template>
  
</xsl:stylesheet>
 
Old March 29th, 2011, 04:20 AM
samjudson's Avatar
Friend of Wrox
 
Join Date: Aug 2007
Posts: 2,128
Thanks: 1
Thanked 189 Times in 188 Posts
Default

Try this instead:

Code:
<xsl:template match="node()[ends-with(local-name(), 'Result')]">
...
</xsl:template>
__________________
/- Sam Judson : Wrox Technical Editor -/

Think before you post: What have you tried?
 
Old March 29th, 2011, 02:22 PM
Registered User
 
Join Date: Mar 2011
Posts: 8
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Sam,

Thanks that did the trick! I did need to change from version 1.0 to 2.0
and add in a namespace for the functions.

I will try the xsl included map next.

BTW: is there a way to get rid of that annoying xmlns=""
<XyzResult xmlns="">
when I have to add back in the element I used in the
match pattern. <xsl:element name="{local-name()}">



Code:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:fn="http://www.w3.org/2005/xpath-functions" 
  xmlns:saxon="http://saxon.sf.net/"  
  xmlns:guid="java:com.my.ConstantsMap" 
  exclude-result-prefixes="saxon guid">

 
  
  <xsl:template match="node()[ends-with(local-name(), 'Result')]">
     <xsl:element name="{local-name()}">
      <xsl:apply-templates select="saxon:parse(.)"  />
      </xsl:element>
  </xsl:template>
 
Old March 30th, 2011, 04:02 AM
samjudson's Avatar
Friend of Wrox
 
Join Date: Aug 2007
Posts: 2,128
Thanks: 1
Thanked 189 Times in 188 Posts
Default

The xmlns="" is because you are creating the new node in a different namespace from the parent node. If you want it to be in the same namespace then specify the namespace in the xsl:element start tag:

Code:
<xsl:element name="{local-name()}" namespace="{namespace-uri()}">
      <xsl:apply-templates select="saxon:parse(.)"  />
      </xsl:element>
__________________
/- Sam Judson : Wrox Technical Editor -/

Think before you post: What have you tried?





Similar Threads
Thread Thread Starter Forum Replies Last Post
Variable substitution in logging.properties Gap_Tooth Apache Tomcat 0 July 21st, 2008 02:50 PM
Correct my xslt for data substitution asap XSLT 0 July 29th, 2006 03:42 PM
How to copy text MICZ Pro VB 6 5 October 29th, 2004 09:57 AM
copy xml to xml (with java script) Umen XML 4 September 14th, 2004 06:51 AM
Substitution for CodeContextObject MKri VB.NET 2002/2003 Basics 0 August 20th, 2004 03:38 AM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.