XSLT选择XML消息的一部分

时间:2013-07-11 00:54:25

标签: xml xslt

我很想找到解决XML消息提取问题的方法。 我所拥有的与以下XML消息类似:

<Orders xmlns="http://AU.InputOrders">
<Order>
<OrderRef>D04004451</OrderRef>
<OrderQty>5</OrderQty>
</Order>
<Order>
<OrderRef>D04004451</OrderRef>
<OrderQty>1</OrderQty>
</Order>
<Order>
<OrderRef>D04004452</OrderRef>
<OrderQty>1</OrderQty>
</Order>
<Order>
<OrderRef>D04004452</OrderRef>
<OrderQty>4</OrderQty>
</Order>
<Order>
<OrderRef>D04004452</OrderRef>
<OrderQty>2</OrderQty>
</Order>
</Orders>

我需要一个XSLT才能获得这一点:

<Orders xmlns="http://AU.InputOrders">
<Order>
<OrderRef>D04004451</OrderRef>
<OrderQty>5</OrderQty>
</Order>
<Order>
<OrderRef>D04004451</OrderRef>
<OrderQty>1</OrderQty>
</Order>
</Orders>

<Orders xmlns="http://AU.InputOrders">
<Order>
<OrderRef>D04004452</OrderRef>
<OrderQty>1</OrderQty>
</Order>
<Order>
<OrderRef>D04004452</OrderRef>
<OrderQty>4</OrderQty>
</Order>
<Order>
<OrderRef>D04004452</OrderRef>
<OrderQty>2</OrderQty>
</Order>
</Orders>

换句话说,我需要根据OrderRef元素值检索Order部分。

感谢。

尝试以下解决方案,两者都有效。 找到另一种解决方案也行之有效。它不使用OrderRef,而是使用Order元素的位置。还是这个人正在做我需要的事情。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:ns0="http://AU.InputOrders">
<xsl:output method="xml" encoding="utf-8" omit-xml-declaration="yes" indent="no"/>
<xsl:template match="/">
   <xsl:element name="Orders" namespace="http://AU.InputOrders">
   <xsl:copy-of select="ns0:Orders/ns0:Order[position() &gt;= 1 and position() &lt;=2]"/>
   </xsl:element>
</xsl:template>
</xsl:stylesheet>

感谢。

2 个答案:

答案 0 :(得分:0)

这是一个XSLT 1.0解决方案,它通过EXSLT扩展函数exsl:document将每个@OrderRef组输出到一个单独的文档(例如“D04004452.xml”)中:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:au="http://AU.InputOrders"
    xmlns:exsl="http://exslt.org/common"
    extension-element-prefixes="exsl"
    version="1.0">

    <xsl:key name="kOR" match="au:Order" use="au:OrderRef"/>

    <xsl:template match="/">
        <xsl:for-each select="//au:Order[ generate-id(.) = generate-id(key('kOR', au:OrderRef)[1] ) ]">
            <xsl:call-template name="handle-group">
                <xsl:with-param name="order-ref" select="au:OrderRef"/>
            </xsl:call-template>
        </xsl:for-each>
    </xsl:template>

    <xsl:template name="handle-group">
        <xsl:param name="order-ref"/>
        <xsl:variable name="fn" select="concat($order-ref,'.xml')"/>
        <exsl:document
            href="{$fn}"
            method="xml"
            indent="yes">
            <xsl:element name="Orders" namespace="http://AU.InputOrders">
                <xsl:for-each select="//au:Order[au:OrderRef=$order-ref]">
                    <xsl:copy-of select="."/>
                </xsl:for-each>
            </xsl:element>
        </exsl:document>
    </xsl:template>

</xsl:stylesheet>

如果您有XSLT 2.0处理器,则可以使用<xsl:result-document/>代替<exsl:document/>

答案 1 :(得分:0)

这是一个相当简单的样式表,可以满足您的要求。 (它使用参数的默认值,但可以覆盖它。)

<xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:au="http://AU.InputOrders">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:param name="orderRef" select="'D04004451'"/>

    <xsl:template match="/*">
        <xsl:copy>
            <xsl:copy-of select="au:Order[au:OrderRef=$orderRef]"/>         
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

如果您需要进行其他处理,请将xsl:copy-of替换为xsl:apply-templates,添加identity transform,并使用模板覆盖它以处理特定部分。