xmlxpathxsltxsd

XPath: How to access information inside xs:appinfo element on an XML Schema


I'm struggling with accessing information inside xs:appinfo element using XPath

I have another well-structured XML inside an xs:appinfo element. Is there a way to directly access a certain element of that XML within the xs:appinfo using XPath? Or is everything within xs:appinfo interpreted as pure text only?

Sample XL Schema:

<xs:schema targetNamespace="ts" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="MyElement">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="MyChildElement1" type="xs:string"/>
        <xs:element name="MyChildElement2" type="xs:string">
          <xs:annotation>
            <xs:appinfo>
              <AppInfoElement1>Hello</AppInfoElement1>
              <AppInfoElement2>Hello</AppInfoElement2>
            </xs:appinfo>
            <xs:documentation xml:lang="en">Any documentation</xs:documentation>
          </xs:annotation>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

How can I access the text of AppInfoElement2 inside the appinfo using XPath?

I tried the following:

//xs:annotation/xs:appinfo[.]
//xs:annotation/xs:appinfo/AppInfoElement2[text()]

Actually I run the XPath in an XSLT select statement as follows (I thought this does not make a difference, but none of the proposed answers work for me):

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="//*[@name='MyChildElement2']" >
    <xsl:copy-of select="xs:annotation/xs:appinfo/AppInfoElement2/text()" />
  </xsl:template>

</xsl:stylesheet>

I'm using a simple C# application to test this.


Solution

  • This XPath,

    //AppInfoElement2/text()
    

    will select all text node children of all AppInfoElement2 elements in the document.

    By using //, you bypass the namespaced elements. Should you ever need to specify namespaced elements in your XPath, see How does XPath deal with XML namespaces?