动态命名空间时,如何在XSLT文件中提及命名空间? [英] How to mention namespace in XSLT file when the namespaces are dynamic?

查看:77
本文介绍了动态命名空间时,如何在XSLT文件中提及命名空间?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要将XML数据存储在DB中,然后从DB中检索xml并转换为PDF.为此,我将XSLT与Apache FOP一起使用.下面的代码与XML文件中的当前名称空间正常工作(我已经将名称空间从 Books.xml 文件复制并粘贴到了 Books.xsl .问题是如果更改了 Books.xml 文件的名称空间,则WebService将会更新,然后我的具有旧名称空间的 Books.xsl 文件在使用Apache FOP生成PDF时出现异常.

注意::如果我按照XML文件中的新名称空间更新Books.xsl文件名称空间,则PDF生成适用于新的XML内容,但不适用于旧的Books.xml内容.

示例:在更新Web服务之前,Books.xml中的旧命名空间如下

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

并假设XML文件中的新名称空间如下

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

这是我的XML内容( 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>

以下是我的xsl内容( 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>

并且Java代码如下

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);
        }

    }

}

任何帮助将不胜感激.

谢谢, RaoPotla

解决方案

如果您事先知道可能的命名空间集是什么,并且它很小,您可以执行以下操作:

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

如果您必须多次进行操作,那会有些混乱,但是它的优点是(?)它不会仅接受任何名称空间中的元素(例如,没有名称空间中的元素).这可能不是优势,具体取决于您的情况.

如果您事先不知道所有可能的名称空间可能是什么,则可以使用这种更通用的解决方案,该解决方案将完全忽略名称空间:

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

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

解决方案

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']" />

这篇关于动态命名空间时,如何在XSLT文件中提及命名空间?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆