XSL Noob
XSL Noob

Reputation: 51

Xpath with Default Namespace

I am trying to get all values of a certain XML element. However, the namespace is not defined. I've tried using the local-name() function but am not having any luck.

    <?xml version="1.0" encoding="utf-8" standalone="yes"?>
        <entry xml:base="https://www.website.com" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
          <id>A</id>
          <title type="text"></title>
          <updated>2015-07-21T02:40:30Z</updated>
          <author>
            <name />
          </author>
          <link rel="edit" title="Application" href="A(1347)" />
          <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/b" type="application/atom+xml;type=feed" title="B" href="A(1347)/B" />
          <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/C" type="application/atom+xml;type=feed" title="C" href="A(1347)/C" />
          <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/D" type="application/atom+xml;type=entry" title="D" href="A(1347)/D" />
          <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/E" type="application/atom+xml;type=feed" title="E" href="A(1347)/E">
            <m:inline>
              <feed>
                <title type="text">E</title>
                <id>1347</id>
                <updated>2015-07-21T02:40:30Z</updated>
                <link rel="self" title="E" href="A(1347)/E" />
                <entry>
                  <id>www.website.com/</id>
                  <title type="text"></title>
                  <updated>2015-07-21T02:40:30Z</updated>
                  <author>
                    <name />
                  </author>
                  <link rel="edit" title="E" href="E(4294)" />
                  <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/A" type="application/atom+xml;type=entry" title="Application" href="E(4294)/A" />
                  <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/D" type="application/atom+xml;type=entry" title="D" href="E(4294)/D" />
                  <category term="APIModel.FileBaseDocuments" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
                  <content type="application/xml">
                    <m:properties>
                      <d:ID m:type="Edm.Int32">4294</d:ID>
                      <d:Type>123</d:Type>
                    </m:properties>
                  </content>
                </entry>
                 <entry>
              <id>www.website.com</id>
              <title type="text"></title>
              <updated>2015-07-21T02:40:30Z</updated>
              <author>
                <name />
              </author>
              <link rel="edit" title="E" href="E(4295)" />
              <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/A" type="application/atom+xml;type=entry" title="A" href="E(4295)/A" />
              <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/D" type="application/atom+xml;type=entry" title="D" href="E(4295)/D" />
              <category term="APIModel.FileBaseDocuments" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
              <content type="application/xml">
                <m:properties>
                  <d:ID m:type="Edm.Int32">4295</d:ID>
                  <d:Type>456</d:Type>
                </m:properties>
              </content>
             </entry>
           </feed>
          </m:inline>
        </link>
      </entry>

I want to retrieve all values inside of "m:properties/d:ID m:type="Edm.Int32" (in this case 4294) but I am getting no luck. So for one file, there would be one "feed" tag filled with multiple "entry" tags. Inside these tags there would be one "m:properties/d:ID m:type="Edm.Int32" which I need to retrieve. Any suggestion on what the correct xPath would be for this situation?

Upvotes: 1

Views: 244

Answers (2)

Sean B. Durkin
Sean B. Durkin

Reputation: 12729

Use the @exclude-result-prefixes attribute to filter out the extraneous namespaces in your output. You don't need to declare the http://www.w3.org/2005/Atom in your transform, unless you need it for other purposes, but even so, it is probably a good thing.

Just match on expression m:properties/d:ID[@m:type='Edm.Int32'] to get your required data.

For example, this transform, when applied to your given input document ....

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
  xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
  xmlns:atom="http://www.w3.org/2005/Atom"
  version="2.0"
  exclude-result-prefixes="xsl d m atom">

<xsl:output encoding="utf-8" omit-xml-declaration="yes" indent="yes" />

<xsl:template match="/">
  <Edm.Int32s>
    <xsl:apply-templates />
  </Edm.Int32s>
</xsl:template>

<xsl:template match="*">
  <xsl:apply-templates />
</xsl:template>

<xsl:template match="text()" />

<xsl:template match="m:properties/d:ID[@m:type='Edm.Int32']">
  <value><xsl:value-of select="text()" /></value>
</xsl:template>  

</xsl:stylesheet>

... yields output ....

<edm.int32s>
  <value>4294</value>
  <value>4295</value>
</edm.int32s>

Note

I have assumed from your question tags that you want an XSLT transform. If you just wanted a simple XPath expression to apply directly to the document, you could use ...

//m:properties/d:ID[@m:type='Edm.Int32']/text()

(passing, of course, the namespace declarations for m and d).

Upvotes: 0

StuartLC
StuartLC

Reputation: 107247

Instead of resorting to namespace agnostic xml by using local-name(), why not register a namespace for the default namespace, e.g. x prefix for xmlns:x="http://www.w3.org/2005/Atom", and then your Xpath would be something like:

//x:feed/x:entry/x:content/m:properties/d:ID[@m:type='Edm.Int32']

The local-name() approach is more verbose:

//*[local-name()='feed']/*[local-name()='entry']/*[local-name()='content']
 /*[local-name()='properties']/*[local-name()='ID' and @m:type='Edm.Int32']

Example of both approaches here

Upvotes: 1

Related Questions