How to mention namespace in XSLT file when the namespaces are dynamic?

こ雲淡風輕ζ 提交于 2019-12-24 03:55:22

问题


I have a requirement to store XML data in DB and after that retrieve xml from DB and convert to PDF. For that I am using XSLT with Apache FOP. The below code is working fine with current namespaces in the XML file(I have copied and pasted the namespaces from Books.xml file to Books.xsl. The Problem is whenever the WebService is updated if the namespace of Books.xml file is changed then my Books.xsl file with old namespaces is giving exception while generating PDF using Apache FOP.

Note : If I update my Books.xsl file namespaces as per the new namespaces in XML file, PDF generation is working for new XML content but not working for old Books.xml content.

Example: Old namespace in Books.xml before Webservice update is as below

<Book xmlns="http://book.com/one/1.1/" xmlns:ns2="http://test2.com/one/1.1/" xmlns:ns3="http://test3.com/one/1.1/" >

and assume new namespace in XML file as below

<Book xmlns="http://book.com/one/1.2/" xmlns:ns2="http://test2.com/one/1.2/" xmlns:ns3="http://test3.com/one/1.2/" >

This is my XML content (BOOK.xml)

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <Book xmlns="http://book.com/one/1.2/" xmlns:ns2="http://test2.com/one/1.2/" xmlns:ns3="http://test3.com/one/1.2/" >
      <Title>Java</Title>
      <ISBN>123</ISBN>
      <Author>Test</Author>
      <BookImage>
        <ns2:ImageName>images1.jpeg</ns2:ImageName>
        <ns2:ImageContent>/aN2r9pT8HwKXpmvvmt2ifpz5xvmt2ifpz5xukZHBb9Wn4FL0xwW/VpD=</ns2:ImageContent>
      </BookImage>
      <BookImage>
        <ns2:ImageName>images2.jpeg</ns2:ImageName>
        <ns2:ImageContent>/aN2r9pT8HwKXpmvvmt2ifpz5xvmt2ifpz5xukZHBb9Wn4FL0xwW/VpD=</ns2:ImageContent>
      </BookImage>
    </Book>

Following is my xsl content(Books.xsl)

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:b="http://book.com/one/1.1/" xmlns:ns2="http://test2.com/one/1.1/" xmlns:ns3="http://test3.com/one/1.1/">

    <xsl:template match="b:Book">

        <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
            <fo:layout-master-set>
                <fo:simple-page-master master-name="ex"
                    page-height="29.7cm" page-width="21cm" margin-top="2cm"
                    margin-bottom="2cm" margin-left="2cm" margin-right="2cm">
                    <fo:region-body />
                </fo:simple-page-master>
            </fo:layout-master-set>
            <fo:page-sequence master-reference="ex">
                <fo:flow flow-name="xsl-region-body">

                    <fo:block space-after="15mm">

                    </fo:block>
                    <fo:block font-size="16pt" font-weight="bold" space-after="5mm">
                        Book Details
                    </fo:block>

                    <fo:block font-size="10pt">
                        <fo:table table-layout="fixed" width="100%"
                            border-collapse="collapse" border="solid 1px black">

                            <fo:table-body>
                                <fo:table-row>
                                    <fo:table-cell border="solid 1px black" padding="1mm">
                                        <fo:block font-weight="bold">Title :</fo:block>
                                    </fo:table-cell>
                                    <fo:table-cell padding="1mm" border="solid 1px black">
                                        <fo:block>
                                            <xsl:value-of select="b:Title" />
                                        </fo:block>
                                    </fo:table-cell>
                                </fo:table-row>

                                <fo:table-row>
                                    <fo:table-cell border="solid 1px black" padding="1mm">
                                        <fo:block font-weight="bold">ISBN :
                                        </fo:block>
                                    </fo:table-cell>
                                    <fo:table-cell padding="1mm" border="solid 1px black">
                                        <fo:block>
                                            <xsl:value-of select="b:ISBN" />
                                        </fo:block>
                                    </fo:table-cell>
                                </fo:table-row>

                                <fo:table-row>
                                    <fo:table-cell border="solid 1px black" padding="1mm">
                                        <fo:block font-weight="bold">Author :</fo:block>
                                    </fo:table-cell>
                                    <fo:table-cell padding="1mm" border="solid 1px black">
                                        <fo:block>
                                        <xsl:value-of select="b:Author" />  
                                        </fo:block>
                                    </fo:table-cell>
                                </fo:table-row>

                                <fo:table-row>
                                    <fo:table-cell border="solid 1px black" padding="1mm">
                                        <fo:block font-weight="bold">Image Names :</fo:block>
                                    </fo:table-cell>
                                    <fo:table-cell padding="1mm" border="solid 1px black">
                                        <fo:block>
                                            <xsl:for-each select="b:BookImage">
                                            <xsl:value-of  select="ns2:ImageName"/>
                                            <xsl:text>&#160;</xsl:text>
                                            </xsl:for-each>
                                        </fo:block>
                                    </fo:table-cell>
                                </fo:table-row>


                            </fo:table-body>
                        </fo:table>
                    </fo:block>
                </fo:flow>
            </fo:page-sequence>
        </fo:root>
    </xsl:template>
</xsl:stylesheet>

and the java code is as follows

import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;

import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.StreamSource;

import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.Fop;
import org.apache.fop.apps.FopFactory;
import org.apache.fop.apps.MimeConstants;

/**
 * This class demonstrates the conversion of an XML file to PDF using
 * JAXP (XSLT) and FOP (XSL-FO).
 */
public class ExampleXML2PDF {

    /**
     * Main method.
     * @param args command-line arguments
     */
    public static void main(String[] args) {
        ExampleXML2PDF exampleXML2PDF = new ExampleXML2PDF();
        exampleXML2PDF.xmlToPDF();
    }


    public void xmlToPDF(){

        try {
            System.out.println("FOP ExampleXML2PDF\n");
            System.out.println("Preparing...");
            System.out.println("Transforming...");

            // configure fopFactory as desired
            final FopFactory fopFactory = FopFactory.newInstance();

            FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
            // configure foUserAgent as desired
            InputStream xslInputStream =  getClass().getResourceAsStream("/resources/Book.xsl");

            InputStream xmlInputStream =  getClass().getResourceAsStream("/resources/Book.xml");

            // Setup output
            OutputStream out = new java.io.FileOutputStream(new File("bin/resources/BookXML2PDF.pdf"));
            out = new java.io.BufferedOutputStream(out);

            try {
                // Construct fop with desired output format
                Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, out);

                // Setup XSLT
                TransformerFactory factory = TransformerFactory.newInstance();
                Transformer transformer = factory.newTransformer(new StreamSource(xslInputStream));

                // Setup input for XSLT transformation
                Source src = new StreamSource(xmlInputStream);

                // Resulting SAX events (the generated FO) must be piped through to FOP
                Result res = new SAXResult(fop.getDefaultHandler());

                // Start XSLT transformation and FOP processing
                transformer.transform(src, res);
            } finally {
                out.close();
            }

            System.out.println("Success!");
        } catch (Exception e) {
            e.printStackTrace(System.err);
            System.exit(-1);
        }

    }

}

Any Help would be appreciated in advance.

Thanks, RaoPotla


回答1:


If you know in advance what the set of possible namespaces will be, and it's a small set, you could do this:

<xsl:template match="b:Book | ns1:Book | ns2:Book">
  ...
    <xsl:value-of select="b:Title | ns1:Title | ns2:Title" />

That gets kind of messy if you have to do it many times, but it has the advantage(?) that it won't accept elements from just any namespace (e.g. elements in no namespace). This may not be an advantage, depending on your situation.

If you don't know in advance what all the possible namespaces might be, you can use this more general solution, which ignores namespaces altogether:

<xsl:template match="*[local-name() = 'Book']">
  ...
    <xsl:value-of select="*[local-name() = 'Title']" />


来源:https://stackoverflow.com/questions/16963316/how-to-mention-namespace-in-xslt-file-when-the-namespaces-are-dynamic

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!