ExtractVariables on XMLPayload - Not working. No variables extracted.

The Created & Weather variable getting blank response as output. please help me out.

Original source message:

<query
    xmlns:yahoo="http://www.yahooapis.com/v1/base.rng" yahoo:count="1" yahoo:created="2018-08-06T06:33:53Z" yahoo:lang="en-US">
  <results>
    <channel>
      <item>
        <yweather:condition
            xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0" text="Breezy"/>
      </item>
    </channel>
  </results>
</query>

Extract Variables:

<ExtractVariables name="Extract-Variables-2">
    <DisplayName>Extract Variables-2</DisplayName>
    <Properties/>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    <Source clearPayload="false">response</Source>
    <VariablePrefix>apigee</VariablePrefix>
    <XMLPayload stopPayloadProcessing="false">
        <Namespaces/>
        <Variable name="Created" type="string">
            <XPath>//query/created</XPath>
        </Variable>
	<Variable name="Weather" type="string">
            <XPath>//query/results/channel/item/condition/text</XPath>
        </Variable>
    </XMLPayload>
</ExtractVariables>

AssignMessage:

<AssignMessage name="Assign-Message-3">
    <DisplayName>Assign Message-3</DisplayName>
    <Properties/>
    <Set>
        <Payload contentType="application/xml">
            <root>
                <city>{apigee.city}</city>
                <created>{apigee.Created}</created>
		<weather>{apigee.Weather}</weather>
            </root>
        </Payload>
    </Set>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    <AssignTo createNew="false" transport="http" type="response"/>
</AssignMessage>

output obtained

<root>
    <city>bangalore</city>
    <created>________</created>
    <weather>________</weather>
</root>
Solved Solved
0 4 695
1 ACCEPTED SOLUTION

You are not considering the XML Namespaces in the XPath.

The defined XPath expression will not work without namespaces that refer to those used in the original document. Use the Namespace tag in ExtractVariable policy to define them. Example:

<ExtractVariables name='EV-1'>
  <Source>contrivedResponse</Source>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    <VariablePrefix>extracted</VariablePrefix>
    <XMLPayload stopPayloadProcessing="false">
      <Namespaces>
        <Namespace prefix='y'>http://www.yahooapis.com/v1/base.rng</Namespace>
        <Namespace prefix='yw'>http://xml.weather.yahoo.com/ns/rss/1.0</Namespace>
      </Namespaces>
        <Variable name="Created" type="string">
            <XPath>/query/@y:created</XPath>
        </Variable>
        <Variable name="Weather" type="string">
            <XPath>/query/results/channel/item/yw:condition/@text</XPath>
        </Variable>
    </XMLPayload>
</ExtractVariables>

Discussion:

  • the "created" attribute is namepace qualified, therefore in the xpath we refer to it as @y:created
  • The query element in your example is not namespace-qualified. Therefore no namespace prefix!
  • The condition element is namespace qualified. ergo, use a prefix
  • The text attribute is not. No namespace prefix.

Alternatively, you can use an XSLT policy to remove Namespaces & then extract using xpath.

In XSL Transform policy,

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>
    <xsl:template match="*">
        <xsl:element name="{local-name(.)}">
            <xsl:apply-templates select="@* | node()"/>
        </xsl:element>
    </xsl:template>
    <xsl:template match="@*">
        <xsl:attribute name="{local-name(.)}">
            <xsl:value-of select="."/>
        </xsl:attribute>
    </xsl:template>
</xsl:stylesheet>
<ExtractVariables name="Extract-Variables-1">
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    <Source clearPayload="false">request</Source>
    <VariablePrefix>apigee</VariablePrefix>
    <XMLPayload stopPayloadProcessing="false">
        <Variable name="weather" type="string">
            <XPath>/query/results/channel/item/condition/@text</XPath>
        </Variable>
        <Variable name="created" type="string">
            <XPath>/query/@created</XPath>
        </Variable>
    </XMLPayload>
</ExtractVariables>

7230-xpath.jpg

View solution in original post

4 REPLIES 4

Hi @pratheek hipparagi, please post a sample XML payload, which you are trying to extract.

BTW XPath should have a single '/' at the beginning.

Hi @siddharth,

<query 
    xmlns:yahoo="http://www.yahooapis.com/v1/base.rng" yahoo:count="1" yahoo:created="2018-08-06T06:33:53Z" yahoo:lang="en-US">
  <results>
    <channel>
      <item>
        <yweather:condition 
            xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0" text="Breezy"/>
      </item>
    </channel>
  </results>
</query>

You are not considering the XML Namespaces in the XPath.

The defined XPath expression will not work without namespaces that refer to those used in the original document. Use the Namespace tag in ExtractVariable policy to define them. Example:

<ExtractVariables name='EV-1'>
  <Source>contrivedResponse</Source>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    <VariablePrefix>extracted</VariablePrefix>
    <XMLPayload stopPayloadProcessing="false">
      <Namespaces>
        <Namespace prefix='y'>http://www.yahooapis.com/v1/base.rng</Namespace>
        <Namespace prefix='yw'>http://xml.weather.yahoo.com/ns/rss/1.0</Namespace>
      </Namespaces>
        <Variable name="Created" type="string">
            <XPath>/query/@y:created</XPath>
        </Variable>
        <Variable name="Weather" type="string">
            <XPath>/query/results/channel/item/yw:condition/@text</XPath>
        </Variable>
    </XMLPayload>
</ExtractVariables>

Discussion:

  • the "created" attribute is namepace qualified, therefore in the xpath we refer to it as @y:created
  • The query element in your example is not namespace-qualified. Therefore no namespace prefix!
  • The condition element is namespace qualified. ergo, use a prefix
  • The text attribute is not. No namespace prefix.

Alternatively, you can use an XSLT policy to remove Namespaces & then extract using xpath.

In XSL Transform policy,

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>
    <xsl:template match="*">
        <xsl:element name="{local-name(.)}">
            <xsl:apply-templates select="@* | node()"/>
        </xsl:element>
    </xsl:template>
    <xsl:template match="@*">
        <xsl:attribute name="{local-name(.)}">
            <xsl:value-of select="."/>
        </xsl:attribute>
    </xsl:template>
</xsl:stylesheet>
<ExtractVariables name="Extract-Variables-1">
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    <Source clearPayload="false">request</Source>
    <VariablePrefix>apigee</VariablePrefix>
    <XMLPayload stopPayloadProcessing="false">
        <Variable name="weather" type="string">
            <XPath>/query/results/channel/item/condition/@text</XPath>
        </Variable>
        <Variable name="created" type="string">
            <XPath>/query/@created</XPath>
        </Variable>
    </XMLPayload>
</ExtractVariables>

7230-xpath.jpg

Thanks @Siddharth Barahalikar , This query got worked Perfectly.