如何使用XSLT基于属性解析相同的命名子元素

时间:2016-06-25 17:09:04

标签: xml xslt

我有以下XML:

<?xml version='1.0' encoding='UTF-8'?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Body>
        <GetGridResult xmlns="http://namespace.net/functions/GetGridResult">
            <GRIDRESULT type="LIST.DATA_ONLY.STORED">
                <DATASPY id="105429" label="VAN" />
                <TOOLBAR jsonclass="object" />
                <GRID>
                    <METADATA>
                        <REQUEST_TYPE_META>LIST.DATA_ONLY.STORED</REQUEST_TYPE_META>
                        <RECORDS>446</RECORDS>
                        <CLIENTROWS>5</CLIENTROWS>
                        <ISSYSTEMUSER>false</ISSYSTEMUSER>
                    </METADATA>
                    <DATA jsonclass="array">
                        <ROW id="1">
                            <D n="5">4451</D><D n="13">BO</D><D n="15">C</D><D n="16">Closed</D><D n="22">0301</D><D n="26">01/26/2015 00:00</D><D n="122">CMBC</D><D n="279">236366</D><D n="608">REP</D><D n="694">BR</D><D n="757">BAD AC</D><D n="1900" />
                            <D n="4998">2</D><D n="6941">A</D>
                        </ROW>
                        <ROW id="2">
                            <D n="5">4451</D><D n="13">BO</D><D n="15">C</D><D n="16">Closed</D><D n="22">0665</D><D n="26">01/23/2015 00:00</D><D n="122">CMBC</D><D n="279">236367</D><D n="608">REP</D><D n="694">BR</D><D n="757">DOOR CONTROL</D><D n="1900" />
                            <D n="4998">2</D><D n="6941">A</D>
                        </ROW>
                    </DATA>
                </GRID>
            </GRIDRESULT>
        </GetGridResult>
    </soapenv:Body>
</soapenv:Envelope>

我需要检索所有行(这里有更多的行),并根据属性获取一些“D”元素以输出以下内容:

<WorkOrderResponse>
    <WorkOrders>
        <WorkOrder>
            <WorkOrderId>236366</WorkOrderId>
            <Description>BAD AC</Description>
            <DateReported>01/26/2015 00:00</DateReported>
            <ClassId>BO</ClassId>
            <ProblemCode>0301</ProblemCode>
            <ActionCode>REP</ActionCode>
        </WorkOrder>
        <WorkOrder>
            <WorkOrderId>236367</WorkOrderId>
            <Description>DOOR CONTROL</Description>
            <DateReported>01/23/2015 00:00</DateReported>
            <ClassId>BO</ClassId>
            <ProblemCode>0665</ProblemCode>
            <ActionCode>REP</ActionCode>
        </WorkOrder>    
    </WorkOrders>
</WorkOrderResponse>

这是我一直在使用的XSL,但是,我似乎无法使其工作。你会看到我试图根据属性“n”拉出D元素,即“D [@ n ='279']”。

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ax21="http://samples.esb.wso2.org/xsd" xmlns:ns="http://namespace.net/functions/GetGridResult/GetGridResult" xmlns:fn="http://www.w3.org/2005/02/xpath-functions" exclude-result-prefixes="ns fn" version="2.0">
    <xsl:output indent="yes" method="xml" omit-xml-declaration="yes"/>
    <xsl:template match="/">
        <WorkOrdersResponse>
            <WorkOrders>
                <xsl:apply-templates />
            </WorkOrders>
        </WorkOrdersResponse>       
    </xsl:template>

    <xsl:template match="DATA"> 
        <xsl:for-each select="ROW">
            <WorkOrder>
                <WorkOrderId>
                    <xsl:value-of select="D[@n='279']"/>
                </WorkOrderId>
                <Description>
                    <xsl:value-of select="D[@n='757']"/>
                </Description>
                <DateReported>
                    <xsl:value-of select="D[@n='26']"/>
                </DateReported>
                <ClassId>
                    <xsl:value-of select="D[@n='13']"/>
                </ClassId>
                <ProblemCode>
                    <xsl:value-of select="D[@n='22']"/>
                </ProblemCode>
                <ActionCode>
                    <xsl:value-of select="D[@n='608']"/>
                </ActionCode>
            </WorkOrder>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

当我针对示例xml运行xsl时,这是当前正在吐出的内容。有任何想法吗?请帮帮我。提前谢谢!

<GetWorkOrdersResponse xmlns:ax21="http://samples.esb.wso2.org/xsd">
  <WorkOrders>
        LIST.DATA_ONLY.STORED 446 5 false

        4451BOCClosed030101/26/2015 00:00CMBC236366REPBRBAD AC 2A

        4451BOCClosed066501/23/2015 00:00CMBC236367REPBRDOOR CONTROL 2A
</WorkOrders>
</GetWorkOrdersResponse>

1 个答案:

答案 0 :(得分:1)

您有几个问题:

首先,您在stylesheet标记中声明此内容:

xmlns:ns="http://namespace.net/functions/GetGridResult/GetGridResult" 

但输入XML中使用的实际命名空间是:

"http://namespace.net/functions/GetGridResult"

接下来,您实际上并未使用已分配给命名空间的前缀 - 因此您的XPath表达式不匹配/选择任何内容。

最后,您将模板应用于您不想处理的节点。由于内置模板规则的操作,这将导致不需要的文本节点出现在输出中。

这是您的样式表,已更正:

<xsl:stylesheet 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:ax21="http://samples.esb.wso2.org/xsd" 
xmlns:ns="http://namespace.net/functions/GetGridResult"
xmlns:fn="http://www.w3.org/2005/02/xpath-functions" 
exclude-result-prefixes="ns fn" 
version="2.0">
    <xsl:output indent="yes" method="xml" omit-xml-declaration="yes"/>


    <xsl:template match="/">
        <WorkOrdersResponse>
            <WorkOrders>
                <xsl:apply-templates select="//ns:DATA"/>
            </WorkOrders>
        </WorkOrdersResponse>       
    </xsl:template>

    <xsl:template match="ns:DATA"> 
        <xsl:for-each select="ns:ROW">
            <WorkOrder>
                <WorkOrderId>
                    <xsl:value-of select="ns:D[@n='279']"/>
                </WorkOrderId>
                <Description>
                    <xsl:value-of select="ns:D[@n='757']"/>
                </Description>
                <DateReported>
                    <xsl:value-of select="ns:D[@n='26']"/>
                </DateReported>
                <ClassId>
                    <xsl:value-of select="ns:D[@n='13']"/>
                </ClassId>
                <ProblemCode>
                    <xsl:value-of select="ns:D[@n='22']"/>
                </ProblemCode>
                <ActionCode>
                    <xsl:value-of select="ns:D[@n='608']"/>
                </ActionCode>
            </WorkOrder>
        </xsl:for-each>
    </xsl:template>

</xsl:stylesheet>

当然,你可以将整个事情简化为:

XSLT 2.0

<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xpath-default-namespace="http://namespace.net/functions/GetGridResult">
<xsl:output indent="yes" method="xml" omit-xml-declaration="yes"/>

<xsl:template match="/"> 
    <WorkOrdersResponse>
        <WorkOrders>
            <xsl:for-each select="//ROW">
                <WorkOrder>
                    <WorkOrderId>
                        <xsl:value-of select="D[@n='279']"/>
                    </WorkOrderId>
                    <Description>
                        <xsl:value-of select="D[@n='757']"/>
                    </Description>
                    <DateReported>
                        <xsl:value-of select="D[@n='26']"/>
                    </DateReported>
                    <ClassId>
                        <xsl:value-of select="D[@n='13']"/>
                    </ClassId>
                    <ProblemCode>
                        <xsl:value-of select="D[@n='22']"/>
                    </ProblemCode>
                    <ActionCode>
                        <xsl:value-of select="nD[@n='608']"/>
                    </ActionCode>
                </WorkOrder>
            </xsl:for-each>
        </WorkOrders>
    </WorkOrdersResponse>    
</xsl:template>

</xsl:stylesheet>

请注意xpath-default-namespace是XSLT 2.0的一项功能。