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

查看:22
本文介绍了当命名空间是动态的时,如何在 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 内容.>

示例:Webservice 更新前 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)

以下是我的 xsl 内容(Books.xsl)

<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">图书详情</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">标题:</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">作者:</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">图像名称:</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:模板></xsl:stylesheet>

和java代码如下

import java.io.File;导入 java.io.InputStream;导入 java.io.OutputStream;导入 javax.xml.transform.Result;导入 javax.xml.transform.Source;导入 javax.xml.transform.Transformer;导入 javax.xml.transform.TransformerFactory;导入 javax.xml.transform.sax.SAXResult;导入 javax.xml.transform.stream.StreamSource;导入 org.apache.fop.apps.FOUserAgent;导入 org.apache.fop.apps.Fop;导入 org.apache.fop.apps.FopFactory;导入 org.apache.fop.apps.MimeConstants;/*** 此类演示使用 XML 文件转换为 PDF* JAXP (XSLT) 和 FOP (XSL-FO).*/公共类 ExampleXML2PDF {/*** 主要方法.* @param args 命令行参数*/公共静态无效主(字符串 [] args){ExampleXML2PDF exampleXML2PDF = new ExampleXML2PDF();示例XML2PDF.xmlToPDF();}公共无效 xmlToPDF(){尝试 {System.out.println("FOP ExampleXML2PDF\n");System.out.println("准备中...");System.out.println("转换...");//根据需要配置 fopFactoryfinal FopFactory fopFactory = FopFactory.newInstance();FOUserAgent foUserAgent = fopFactory.newFOUserAgent();//根据需要配置 foUserAgentInputStream xslInputStream = getClass().getResourceAsStream("/resources/Book.xsl");InputStream xmlInputStream = getClass().getResourceAsStream("/resources/Book.xml");//设置输出OutputStream out = new java.io.FileOutputStream(new File("bin/resources/BookXML2PDF.pdf"));out = new java.io.BufferedOutputStream(out);尝试 {//用所需的输出格式构造 fopFop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, out);//设置 XSLTTransformerFactory 工厂 = TransformerFactory.newInstance();Transformer 变压器 = factory.newTransformer(new StreamSource(xslInputStream));//设置 XSLT 转换的输入Source src = new StreamSource(xmlInputStream);//产生的 SAX 事件(生成的 FO)必须通过管道传送到 FOP结果 res = new SAXResult(fop.getDefaultHandler());//启动 XSLT 转换和 FOP 处理变压器.transform(src, res);} 最后 {关闭();}System.out.println("成功!");} 捕获(异常 e){e.printStackTrace(System.err);System.exit(-1);}}}

如有任何帮助,我们将不胜感激.

谢谢,饶波特拉

解决方案

如果你事先知道可能的命名空间集合是什么,而且它是一个小集合,你可以这样做:

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

如果你必须多次这样做,那会有点混乱,但它有一个优点(?),它不会接受来自任何命名空间的元素(例如,没有命名空间的元素).根据您的情况,这可能不是优势.

如果你事先不知道所有可能的命名空间是什么,你可以使用这个更通用的解决方案,它完全忽略命名空间:

...<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天全站免登陆