[xsd-users] Arbitrary XML inside XML element

Boris Kolpackov boris at codesynthesis.com
Fri Aug 8 12:33:06 EDT 2008


Hi Attila,

Attila <atteeela at gmail.com> writes:

> Now I would want a way to retrieve all "skipped" content underneath the
> <message> element as a string. I do not want callbacks on each any'ed
> element (as I have indicated I want to skip processing the contents).

processContent="skip" in XML Schema means that the content will not be
validated, not that it won't be accessible to the application (e.g., in
DOM or SAX). Furthermore, it is not possible for an XML parser to really
skip a chunk of document since it needs to parse it in order to determine
where to stop skipping (i.e., it needs to detect the closing tag of a
fragment you want skipped).


> XML Instance:
> 
> <message>
>    <to>a</to>
>    <from>b</from>
>    <subject>c</subject>
>    <myElement>
>       <asdf>...</asdf>
>    </myElement>
> </message
> 
> Would there be a way for me to retrieve:
> 
>    <myElement>
>       <asdf>...</asdf>
>    </myElement>
> 
> As text when processing <message>? 

The parser will deliver this fragment as raw SAX callbacks which
you can override to construct an XML string from it. For example:

struct message_pimpl: message_pskel
{
  message_pimpl ()
    : depth_ (0)
  {
  }

  virtual void
  _start_any_element (const xml_schema::ro_string& ns,
                      const xml_schema::ro_string& name,
                      const xml_schema::ro_string* type)
  {
    if (depth_ == 0)
    {
      start_tag_ = false;
      wildcard_content_.clear ();
    }

    if (start_tag_)
      wildcard_content_ += ">"; // Close previous start tag.
    
    wildcard_content_ += "<";
    wildcard_content_ += name;
    start_tag_ = true;
    depth_++;
  }

  virtual void
  _any_attribute (const xml_schema::ro_string& ns,
                  const xml_schema::ro_string& name,
                  const xml_schema::ro_string& value)
  {  
    wildcard_content_ += " ";
    wildcard_content_ += name;
    wildcard_content_ += "=\"";
    wildcard_content_ += value;
    wildcard_content_ += "\"";
  }

  virtual void
  _end_any_element (const xml_schema::ro_string& ns, 
                    const xml_schema::ro_string& name)
  {
    if (start_tag_)
    {
      wildcard_content_+= "/>" // Empty content element.
      start_tag_ = false;
    }
    else
    {
      wildcard_content_ += "</";
      wildcard_content_ += name;
      wildcard_content_ += ">";
    }

    depth_--;
  }

  virtual void
  _any_characters (const ro_string& s)
  {
    if (start_tag_)
    {
      wildcard_content_ += ">"; // Close previous start tag.
      start_tag_ = false;
    }

    wildcard_content_ += s;
  }

private:
  size_t depth_;
  bool start_tag_;
  string wildcard_content_;
};

Boris




More information about the xsd-users mailing list