Problems with multiple multiple-level inclusion of DTDs

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • junyang@gmail.com

    Problems with multiple multiple-level inclusion of DTDs

    Hi all,

    I have one DTD fragment, base.dtd, that contains a bunch of useful
    element definitions (say an element named "base"), and two DTD
    fragments, a.dtd and b.dtd, that each build on base.dtd and defines a
    few more elements. I use an entity to include base.dtd in a.dtd and
    b.dtd. For example, in a.dtd:

    <!ENTITY % include.base SYSTEM "base.dtd">
    %include.base
    <!ELEMENT a (base+)>

    In b.dtd:

    <!ENTITY % include.base SYSTEM "base.dtd">
    %include.base
    <!ELEMENT b (#PCDATA|base)* >

    In my XML documents, if I just want to use element a (or b), I simply
    need to entity-include a.dtd, and that will automatically include
    base.dtd, which is nice.

    However, the trouble comes in when I entity-include both a.dtd and
    b.dtd. The problem is that the element "base" will be included twice
    (once via a.dtd->base.dtd and another time via b.dtd->base.dtd). Note
    that multiple definitions of the "include.ba se" entity is fine (as per
    XML standard), but multiple definitions of any element is disallowed.

    I explored a few workarounds but couldn't find any clean solution (for
    example, something that resembles C/C++'s #ifndef and #define). Any
    suggestions will be appreciated!

    --- Jun Y.
  • Peter Flynn

    #2
    Re: Problems with multiple multiple-level inclusion of DTDs

    junyang@gmail.c om wrote:
    Hi all,
    >
    I have one DTD fragment, base.dtd, that contains a bunch of useful
    element definitions (say an element named "base"), and two DTD
    fragments, a.dtd and b.dtd, that each build on base.dtd and defines a
    few more elements. I use an entity to include base.dtd in a.dtd and
    b.dtd. For example, in a.dtd:
    >
    <!ENTITY % include.base SYSTEM "base.dtd">
    %include.base
    <!ELEMENT a (base+)>
    >
    In b.dtd:
    >
    <!ENTITY % include.base SYSTEM "base.dtd">
    %include.base
    <!ELEMENT b (#PCDATA|base)* >
    >
    In my XML documents, if I just want to use element a (or b), I simply
    need to entity-include a.dtd, and that will automatically include
    base.dtd, which is nice.
    >
    However, the trouble comes in when I entity-include both a.dtd and
    b.dtd. The problem is that the element "base" will be included twice
    (once via a.dtd->base.dtd and another time via b.dtd->base.dtd). Note
    that multiple definitions of the "include.ba se" entity is fine (as per
    XML standard), but multiple definitions of any element is disallowed.
    The technique is to use parameter-entity switches.

    In a.dtd:

    <!ENTITY % use.base.from.a "INCLUDE">
    <![%use.base.from. a;[
    %include.base;
    <!ENTITY % use.base.from.b "IGNORE">
    ]]>

    In b.dtd

    <!ENTITY % use.base.from.b "INCLUDE">
    <![%use.base.from. b;[
    %include.base;
    <!ENTITY % use.base.from.a "IGNORE">
    ]]>

    This way, whichever one you invoke first will prevent the other one from
    being activated.

    Better would be to paramaterise a and b alone, and invoke your base in
    your document type declaration with a PE switch to include whichever or
    a and b (or both) that you require for the instance.

    ///Peter

    Comment

    • junyang@gmail.com

      #3
      Re: Problems with multiple multiple-level inclusion of DTDs

      On Jul 26, 4:40 pm, Peter Flynn <peter.n...@m.s ilmaril.iewrote :
      >
      The technique is to use parameter-entity switches.
      >
      In a.dtd:
      >
      <!ENTITY % use.base.from.a "INCLUDE">
      <![%use.base.from. a;[
      %include.base;
      <!ENTITY % use.base.from.b "IGNORE">
      ]]>
      >
      In b.dtd
      >
      <!ENTITY % use.base.from.b "INCLUDE">
      <![%use.base.from. b;[
      %include.base;
      <!ENTITY % use.base.from.a "IGNORE">
      ]]>
      >
      This way, whichever one you invoke first will prevent the other one from
      being activated.
      This would work, except that now a.dtd would need to know about b.dtd,
      and vice versa, which is difficult to keep manage if there are many
      potential includers of base.dtd...
      Better would be to paramaterise a and b alone, and invoke your base in
      your document type declaration with a PE switch to include whichever or
      a and b (or both) that you require for the instance.
      This is what I am doing for now, though users of a.dtd and b.dtd have
      to manually manage inclusion.

      Another possibility I thought of is to have an exclude-base-
      includers.dtd file that sets all PE switches to false. This file would
      be included by base.dtd. Each includer of base.dtd would set the its
      own PE switch to true, and then include base.dtd. End users are hidden
      from all this mess, but the downside of this approach is that the
      exclude-base-includers.dtd file needs to be maintained.

      --- Jun Y.

      Comment

      • Peter Flynn

        #4
        Re: Problems with multiple multiple-level inclusion of DTDs

        junyang@gmail.c om wrote:
        On Jul 26, 4:40 pm, Peter Flynn <peter.n...@m.s ilmaril.iewrote :
        [snip]
        >Better would be to paramaterise a and b alone, and invoke your base in
        >your document type declaration with a PE switch to include whichever or
        >a and b (or both) that you require for the instance.
        >
        This is what I am doing for now, though users of a.dtd and b.dtd have
        to manually manage inclusion.
        >
        Another possibility I thought of is to have an exclude-base-
        includers.dtd file that sets all PE switches to false. This file would
        be included by base.dtd. Each includer of base.dtd would set the its
        own PE switch to true, and then include base.dtd. End users are hidden
        from all this mess, but the downside of this approach is that the
        exclude-base-includers.dtd file needs to be maintained.
        It's usually far easier to manage if you make base.dtd the external
        entity referenced by the DOCTYPE Declaration, and let users add their
        own selection of a, b, ... using a PE in the internal subset.

        <!DOCTYPE whatever SYSTEM "/some/uri/for/base.dtd" [
        <!ENTITY % a "INCLUDE">
        ]>

        and do all your entity management and file inclusion in base.dtd, a.ent,
        b.ent, or whatever.

        ///Peter

        Comment

        • junyang@gmail.com

          #5
          Re: Problems with multiple multiple-level inclusion of DTDs

          On Jul 27, 4:14 pm, Peter Flynn <peter.n...@m.s ilmaril.iewrote :
          It's usually far easier to manage if you make base.dtd the external
          entity referenced by the DOCTYPE Declaration, and let users add their
          own selection of a, b, ... using a PE in the internal subset.
          >
          <!DOCTYPE whatever SYSTEM "/some/uri/for/base.dtd" [
          <!ENTITY % a "INCLUDE">
          ]>
          >
          and do all your entity management and file inclusion in base.dtd, a.ent,
          b.ent, or whatever.
          Thanks! This is much cleaner than the exclude-base-includers.dtd
          trick I thought of earlier.

          --- Jun Y.

          Comment

          Working...