有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java XSLT:使用xpath表达式提取同级节点的最后x位

我试图用xpath提取“红色”同级的最后4个数字

源xml如下所示:

... 
<node2>
    <key><![CDATA[RED]]></key>
    <value><![CDATA[98472978241908]]></value>

    ... more key value pairs here...  

</node2>
...

当我使用以下xpath时: /nodelevelX/nodelevelY/node2/key[text()='RED']/following-sibling::value

我在输出中有完整的数字,然后我尝试用xpath表达式提取数字:

/nodelevelX/nodelevelY/node2/key[text()='RED']/following-sibling::value/text()[substring(., string-length(.)-4)]

我还有完整的号码。子字符串函数似乎不起作用

我的xsl头是:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

我认为有一个小错误,但我看不出在哪里。我关注了许多关于SO和其他学校的讨论,并试图遵循这些建议,但没有成功

更新:背景:

我使用以下标识将所有节点从源XML复制到目标(XML) 我在xsl:template中为某些节点应用特定规则:

<!-- This copy the whole source XML in destination  -->
    <xsl:template match="node() | @*">
        <xsl:copy>
            <xsl:apply-templates select="node() | @*" />
        </xsl:copy>
    </xsl:template>

    <!-- specific rules for some nodes -->

    <xsl:template match="/nodeDetails">
        <mynewnode>
            <!-- here I take the whole value and it s working -->
            <someVal><xsl:value-of select="/nodeDetails/nodeX/key[text()='ANOTHER_KEY']/following-sibling::value" /></someVal>
            <!-- FIXME substring does not work now -->
            <redVal><xsl:value-of select="/nodeDetails/nodeX/key[text()='RED']/following-sibling::value/text()[substring(.,string-length(.)-4)]" /></redVal>
        </mynewnode>
    </xsl:template>

对于转换,我使用Java(JDK 6)中junit类的以下代码:

@Test
public void transformXml() throws TransformerException {

    TransformerFactory factory = TransformerFactory.newInstance();
    Source xslt = new StreamSource(getClass().getResourceAsStream("contract.xsl"));
    Transformer transformer = factory.newTransformer(xslt);
    Source input = new StreamSource(getClass().getResourceAsStream("source.xml"));
    Writer output = new StringWriter();
    transformer.transform(input, new StreamResult(output));
    System.out.println("output=" + output.toString());

}

共 (2) 个答案

  1. # 1 楼答案

    使用XPath 2.0表达式

    /nodelevelX/nodelevelY/node2/key[text()='RED']
                        /following-sibling::*[1][self::value]
                                /substring(., string-length() -3)
    

    基于XSLT2.0的验证:

    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output method="text"/>
     <xsl:strip-space elements="*"/>
    
     <xsl:template match="/">
         <xsl:copy-of select=
         "/nodelevelX/nodelevelY/node2/key[text()='RED']
                        /following-sibling::*[1][self::value]
                                /substring(., string-length() -3)"/>
     </xsl:template>
    </xsl:stylesheet>
    

    当此转换应用于以下XML文档时

    <nodelevelX>
        <nodelevelY>
            <node2>
                <key>GREEN</key>
                <value>0123456789</value>
                <key>RED</key>
                <value>98472978241908</value>
                <key>BLACK</key>
                <value>987654321</value>
            </node2>
        </nodelevelY>
    </nodelevelX>
    

    计算XPath表达式,并将计算结果复制到输出:

    1908
    
  2. # 2 楼答案

    您当前的XPath将计算为一个节点集,但您需要的是一个字符串。请尝试以下方式:

    <xsl:variable name="value" 
                  select="/nodelevelX/nodelevelY/node2/key[. = 'RED']
                          /following-sibling::value[1]" />
    <xsl:value-of select="substring($value, string-length($value) - 3)" />
    

    虽然为了确定答案,我需要查看XSLT中试图输出该值的部分