XSLT:访问for-each中的Java对象属性/方法

时间:2014-11-25 15:39:47

标签: java arrays xslt

所以我有一些Java对象的数组:

SomeElementsArray[]

我试图访问XSLT样式表文件中每个对象的属性,如下所示:

<xsl:for-each select="//data/SomeElementsArray">
 <xsl:variable name="dto" select="current()" />
  <block>
    <xsl:value-of select="someObjectAttribute" />
  </block>
</xsl:for-each>

问题在于我在很多方面试图获得一些东西,但我没有得到任何结果。如果我只输出$dto变量,我会得到对象的引用,如下所示:

[Lcom.domain.core.model.SomeElements;@3f38dd0

我在这个XSLT中使用了许多变量作为名为&#39; data&#39;(Map<String, Object> data = new HashMap<String, Object>();)的Map。例如,我可以访问“数据/某些内容”。它显示了它应该显示的内容,这个数组映射在&#39; data/SomeElementsArray&#39;。

我做错了什么?数组中对象的所有字段都是公共的,我也有getter和setter ....请帮忙!

1 个答案:

答案 0 :(得分:0)

以下是解决方案:

  1. 首先,Map中的值不能是任何类型的对象。 XSLT(至少我使用的版本 - 1.0)仅支持原始值(即String,int,boolean,Nodes等)。它不能是我传递的数组的类型(即SomeElementsArray [])。在某种程度上,必须将值带到原语。
  2. 为了传递该数组,必须完成自定义转换,这意味着对于HashMaps,ArrayLists等类型,我需要编写一些生成XML / XSLT节点的代码。例如,以下是一些以递归方式执行转换的代码:

    private static void field(StringBuilder builder, String tag, Object content) {
        if(content == null) {
            return;
        } else if(content instanceof Iterable) {
            for(Object object: (Iterable) content) {
                field(builder, tag, object);
        }
        return;
    } else if(content.getClass().isArray() && !(content instanceof  Map)) {
        for(int i = 0; i < Array.getLength(content); i++) {
            field(builder, tag, Array.get(content, i));
        }
        return;
    }
    if(content instanceof Double || content instanceof Float) content = String.format("%.2f", content);
    if(content instanceof Date) content = dateFormat.format(content);
    if(content instanceof Calendar) content = dateFormat.format(new Date(((Calendar) content).  getTimeInMillis()));
    builder.append("<");
    builder.append(tag);
    builder.append(">");
    if(content instanceof Map) {
        Map map = (Map) content;
        for(Object object: map.entrySet()) {
            Map.Entry entry = (Map.Entry) object;
            field(builder, (String) entry.getKey(), entry.getValue());
        }
    } else {
        try { //making sure that characters are decoded in case they
            //are encoded
            content = URLDecoder.decode(content.toString(), "UTF-8");
        } catch (UnsupportedEncodingException e) {
            //silently ignores error
            //and content will be untouched
        }
        String value = content.toString().
                replace("&", "&amp;").
                replace("<", "&lt;").
                replace(">", "&gt;").
                replace("'", "&apos;").
                replace("\"", "&quot;");
        builder.append(value);
    }
    builder.append("</");
    builder.append(tag);
    builder.append(">");}
    
  3. 基本上,上面的转换允许Map中的任何类型的值,因此现在可以让Map<String, ArrayList<Map<String, Map<String, Map<String, String>>>>没有问题。 XML的编写方式如下:

    public static void write(String stylesheetText, Map<String, ?> input, OutputStream output) {
        StringBuilder xml = new StringBuilder();
        xml.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n");
        xml.append("<data>");
        for(Map.Entry<String, ?> entry: input.entrySet()) {
            field(xml, entry.getKey(), entry.getValue());
        }
        xml.append("</data>");
        FopFactory fopFactory = FopFactory.newInstance();
        FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
        try {
            TransformerFactory factory = TransformerFactory.newInstance();
            StreamSource source = new StreamSource(new StringReader(stylesheetText));
            Transformer transformer = factory.newTransformer(source);
            transformer.setParameter("versionParam", "2.0");
            Source s = new StreamSource(new StringReader(xml.toString()));
            Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, output);
            Result result = new SAXResult(fop.getDefaultHandler());
            transformer.transform(s, result);
            output.close();
        } catch (IOException exception) {
            throw new PdfException(exception);
        } catch (TransformerException exception) {
            throw new PdfException(exception);
        } catch (TransformerFactoryConfigurationError exception) {
            throw new PdfException(exception);
        } catch (FOPException exception) {
            throw new PdfException(exception);
        }
    }
    
    1. 考虑到第1点和第2点,循环可以像问题一样完成,没有问题。
    2. 就我而言,&#34; SomeElementsArray&#34;为简单起见,我是ArrayList<Map<String, String>>。它也可以是Map,但是每个子根节点都有一个唯一的名称,因此必须进行额外的解析。

      我希望有一天能帮助某人,因为我在艰难的过程中学到了这一点。