Loading ...
Sorry, an error occurred while loading the content.

Re: [XSL-FO] reading from external documents in XSLFO

Expand Messages
  • W. Eliot Kimber
    ... This is an XSLT question and should really be asked on the XSLT mailing list maintained by Mulberry Technologies:
    Message 1 of 8 , Apr 4, 2007
    • 0 Attachment
      mina_hurray wrote:
      > Hi:
      >
      > I was not sure how to frame the subject and question for this porblem.
      > Basically, I am trying to read from an external XML file using
      > document() function.

      This is an XSLT question and should really be asked on the XSLT mailing
      list maintained by Mulberry Technologies:
      http://www.mulberrytech.com/xsl/xsl-list/index.html

      In both XSLT 1 and 2 you should be able create a new document and then
      examine it using normal select and match processing, but if you use
      "value-of" then you'll just get it's string value.

      That is, something like:

      <xsl:if test="string(document($docuri)/company/prod) = 'box'">
      <xsl:message>*** Found a box</xsl:message>
      </xsl:if>

      In XSLT 1 it may not work to assign document() to a variable (I don't
      remember now, I've been using XSLT 2 for too long) but you shouldn't
      worry about calling document() multiple times on the same URI--any good
      XSLT engine should only parse a given document once within a script run.

      In XSLT 2 you can definitely assign document() to a variable you will
      have variable that contains a document node and not a string (unless you
      explicitly set the datatype of the variable to string).

      Cheers,

      E.

      --
      W. Eliot Kimber
      Professional Services
      Innodata Isogen
      8500 N. Mopac, Suite 402
      Austin, TX 78759
      (214) 954-5198

      ekimber@...
      www.innodata-isogen.com
    • G. Ken Holman
      ... You are taking a programmer s approach to the problem, like many of my students try to do until they learn some principles of XSLT. ... Yes ... you do
      Message 2 of 8 , Apr 4, 2007
      • 0 Attachment
        At 2007-04-04 21:16 +0000, mina_hurray wrote:
        >I was not sure how to frame the subject and question for this porblem.
        >Basically, I am trying to read from an external XML file using
        >document() function.
        >My external file has:
        >...
        >I have an internal XML file which has:
        >...
        >Now I pass the paramter "name" thru the style sheet. Suppose I pass
        >"xyz" i want to check if the <prod> tag in the internal XML document
        >matches any of the<product> in the externak XML file. If it does I
        >want it to display "Hello world". How can I achieve this?
        >
        >The main issue is that <product> in the external file doesnot have a
        >wrapper around it, so when I store it in a variable and make a call to
        >it, it returs b0x chocolate pencil.

        You are taking a "programmer's approach" to the problem, like many of
        my students try to do until they learn some principles of XSLT.

        >Suppose I store this in a variable
        >test1, and store <company><prod> value in test2, I cannot compare each
        >value of test1 against test2, since test1 will have all three in this
        >fashion
        >
        >Box Chocolae pencil.

        Yes ... you do not need to use variables to accomplish what you need.

        >How can I match <company><prod> value to each single value in the
        >external xml?

        It is inherent in XSLT to be able to compare node sets. The
        comparison is initialized to false, and all of the nodes of one
        operand are compared to all of the nodes in the other operand. As
        soon as any comparison is true, the comparisons stop and true is
        returned. If you get false, then you know that there are no matches
        between the two node sets. You are not told *where* you get a true,
        you only get a true if *any* of the comparisons return true.

        So, using this principle, an example below shows that it is very easy
        in XSLT to get what I understand you to want.

        I hope this helps.

        . . . . . . . . . . . . Ken

        T:\ftemp>type mina0.xml
        <company>
        <name>xyz</name>
        <product>box</product>
        <product>chocolates</product>
        <product>pencil</product>
        </company>

        T:\ftemp>type mina1.xml
        <company>
        <prod>box</prod>
        </company>

        T:\ftemp>type mina2.xml
        <company>
        <prod>xyz</prod>
        </company>

        T:\ftemp>type mina.xsl
        <?xml version="1.0" encoding="US-ASCII"?>
        <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        version="1.0">

        <xsl:output method="text"/>

        <xsl:template match="/">
        <xsl:message>
        <xsl:choose>
        <xsl:when test="company/prod = document('mina0.xml')/company/product">
        The target document product is in the set of company products.
        </xsl:when>
        <xsl:otherwise>
        The target document product is not in the set of company products.
        </xsl:otherwise>
        </xsl:choose>
        </xsl:message>
        </xsl:template>

        </xsl:stylesheet>
        T:\ftemp>xslt mina1.xml mina.xsl con

        The target document product is in the set of company products.


        T:\ftemp>xslt mina2.xml mina.xsl con

        The target document product is not in the set of company products.


        T:\ftemp>

        --
        World-wide corporate, govt. & user group XML, XSL and UBL training
        RSS feeds: publicly-available developer resources and training
        G. Ken Holman mailto:gkholman@...
        Crane Softwrights Ltd. http://www.CraneSoftwrights.com/f/
        Box 266, Kars, Ontario CANADA K0A-2E0 +1(613)489-0999 (F:-0995)
        Male Cancer Awareness Aug'05 http://www.CraneSoftwrights.com/f/bc
        Legal business disclaimers: http://www.CraneSoftwrights.com/legal
      • W. Eliot Kimber
        ... Ken reminds me that this isn t actually good in either XSLT 1, because 1 string acts on the node in document order, while in 2 string doesn t allow a node
        Message 3 of 8 , Apr 4, 2007
        • 0 Attachment
          W. Eliot Kimber wrote:
          > In both XSLT 1 and 2 you should be able create a new document and then
          > examine it using normal select and match processing, but if you use
          > "value-of" then you'll just get it's string value.
          >
          > That is, something like:
          >
          > <xsl:if test="string(document($docuri)/company/prod) = 'box'">
          > <xsl:message>*** Found a box</xsl:message>
          > </xsl:if>

          Ken reminds me that this isn't actually good in either XSLT 1, because 1
          string acts on the node in document order, while in 2 string doesn't
          allow a node set (which is what the expression
          "document($docuri)/company/prod" returns), only a single node.

          Doh!

          Cheers,

          E.

          --
          W. Eliot Kimber
          Professional Services
          Innodata Isogen
          8500 N. Mopac, Suite 402
          Austin, TX 78759
          (214) 954-5198

          ekimber@...
          www.innodata-isogen.com
        • mina_hurray
          As usual this has helped me resolve my issue. This is part of a bigger issue that I have where I am filtering data. It is complicated and although I have a
          Message 4 of 8 , Apr 5, 2007
          • 0 Attachment
            As usual this has helped me resolve my issue. This is part of a bigger
            issue that I have where I am filtering data. It is complicated and
            although I have a working solution I wanted to know if there is a
            better approach to this problem.

            I have my input XML which has 5 levels <level1>...<level5> and level
            is the parent level for all these levels, while level2 is parent for
            level3, level 3 is parent of level4 and level 4 is parent of level5.
            Now I apply some conditions to filter out content at these levels.
            These levels are also formatted with number 1. So if I have some
            levels inbetween to be filtered out, I also want them to be numbered
            sequentially.

            sinple Example:

            <level1>
            <text>Some cond1 here </text>

            <level1>
            <level1>
            <text>Some cond2 here </text>

            <level1>
            <level1>
            <text>one more cond1 here </text>

            <level1>


            Expected output for 'cond1' is:

            1. Some cond1 here
            2. one more cond1 here

            Now, the way I am doing it in FO is using <xsl:number> and counting
            the levels where conditioning applies or does not.

            <xsl:number count="level[....whole set of filtering here...]"/>

            This is getting really cumbersome and I would like to know if there is
            any otehr way n XSLFO to approach this in a better optimised way.

            Thanks in advance

            --- In XSL-FO@yahoogroups.com, "G. Ken Holman" <gkholman@...> wrote:
            >
            > At 2007-04-04 21:16 +0000, mina_hurray wrote:
            > >I was not sure how to frame the subject and question for this porblem.
            > >Basically, I am trying to read from an external XML file using
            > >document() function.
            > >My external file has:
            > >...
            > >I have an internal XML file which has:
            > >...
            > >Now I pass the paramter "name" thru the style sheet. Suppose I pass
            > >"xyz" i want to check if the <prod> tag in the internal XML document
            > >matches any of the<product> in the externak XML file. If it does I
            > >want it to display "Hello world". How can I achieve this?
            > >
            > >The main issue is that <product> in the external file doesnot have a
            > >wrapper around it, so when I store it in a variable and make a call to
            > >it, it returs b0x chocolate pencil.
            >
            > You are taking a "programmer's approach" to the problem, like many of
            > my students try to do until they learn some principles of XSLT.
            >
            > >Suppose I store this in a variable
            > >test1, and store <company><prod> value in test2, I cannot compare each
            > >value of test1 against test2, since test1 will have all three in this
            > >fashion
            > >
            > >Box Chocolae pencil.
            >
            > Yes ... you do not need to use variables to accomplish what you need.
            >
            > >How can I match <company><prod> value to each single value in the
            > >external xml?
            >
            > It is inherent in XSLT to be able to compare node sets. The
            > comparison is initialized to false, and all of the nodes of one
            > operand are compared to all of the nodes in the other operand. As
            > soon as any comparison is true, the comparisons stop and true is
            > returned. If you get false, then you know that there are no matches
            > between the two node sets. You are not told *where* you get a true,
            > you only get a true if *any* of the comparisons return true.
            >
            > So, using this principle, an example below shows that it is very easy
            > in XSLT to get what I understand you to want.
            >
            > I hope this helps.
            >
            > . . . . . . . . . . . . Ken
            >
            > T:\ftemp>type mina0.xml
            > <company>
            > <name>xyz</name>
            > <product>box</product>
            > <product>chocolates</product>
            > <product>pencil</product>
            > </company>
            >
            > T:\ftemp>type mina1.xml
            > <company>
            > <prod>box</prod>
            > </company>
            >
            > T:\ftemp>type mina2.xml
            > <company>
            > <prod>xyz</prod>
            > </company>
            >
            > T:\ftemp>type mina.xsl
            > <?xml version="1.0" encoding="US-ASCII"?>
            > <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
            > version="1.0">
            >
            > <xsl:output method="text"/>
            >
            > <xsl:template match="/">
            > <xsl:message>
            > <xsl:choose>
            > <xsl:when test="company/prod =
            document('mina0.xml')/company/product">
            > The target document product is in the set of company products.
            > </xsl:when>
            > <xsl:otherwise>
            > The target document product is not in the set of company
            products.
            > </xsl:otherwise>
            > </xsl:choose>
            > </xsl:message>
            > </xsl:template>
            >
            > </xsl:stylesheet>
            > T:\ftemp>xslt mina1.xml mina.xsl con
            >
            > The target document product is in the set of company products.
            >
            >
            > T:\ftemp>xslt mina2.xml mina.xsl con
            >
            > The target document product is not in the set of company
            products.
            >
            >
            > T:\ftemp>
            >
            > --
            > World-wide corporate, govt. & user group XML, XSL and UBL training
            > RSS feeds: publicly-available developer resources and training
            > G. Ken Holman mailto:gkholman@...
            > Crane Softwrights Ltd. http://www.CraneSoftwrights.com/f/
            > Box 266, Kars, Ontario CANADA K0A-2E0 +1(613)489-0999 (F:-0995)
            > Male Cancer Awareness Aug'05 http://www.CraneSoftwrights.com/f/bc
            > Legal business disclaimers: http://www.CraneSoftwrights.com/legal
            >
          • G. Ken Holman
            ... Without knowing more of your input data and your conditions, I think I would have addressed this the same way with . But I wonder why you
            Message 5 of 8 , Apr 5, 2007
            • 0 Attachment
              At 2007-04-05 15:03 +0000, mina_hurray wrote:
              >As usual this has helped me resolve my issue. This is part of a bigger
              >issue that I have where I am filtering data. It is complicated and
              >although I have a working solution I wanted to know if there is a
              >better approach to this problem.
              >
              >I have my input XML which has 5 levels <level1>...<level5> and level
              >is the parent level for all these levels, while level2 is parent for
              >level3, level 3 is parent of level4 and level 4 is parent of level5.
              >Now I apply some conditions to filter out content at these levels.
              >These levels are also formatted with number 1. So if I have some
              >levels inbetween to be filtered out, I also want them to be numbered
              >sequentially.
              >
              >sinple Example:
              >
              ><level1>
              ><text>Some cond1 here </text>
              >
              ><level1>
              ><level1>
              ><text>Some cond2 here </text>
              >
              ><level1>
              ><level1>
              ><text>one more cond1 here </text>
              >
              ><level1>
              >
              >
              >Expected output for 'cond1' is:
              >
              >1. Some cond1 here
              >2. one more cond1 here
              >
              >Now, the way I am doing it in FO is using <xsl:number> and counting
              >the levels where conditioning applies or does not.
              >
              ><xsl:number count="level[....whole set of filtering here...]"/>
              >
              >This is getting really cumbersome and I would like to know if there is
              >any otehr way n XSLFO to approach this in a better optimised way.

              Without knowing more of your input data and your conditions, I think
              I would have addressed this the same way with <xsl:number>. But I
              wonder why you filter first and then count ... using level="any" you
              might be able to do the counting on the original data set.

              However, from your description, <xsl:number/> is appropriate because
              you are counting constructs in the source node tree. You could use
              XPath and the preceding:: and ancestor:: axis to replicate the
              counting ... or just the preceding-sibling:: axis if all of your
              constructs are siblings, but since that is built in to <xsl:number/>
              you are probably using the most appropriate construct.

              Yes, sometimes elaborate predicates are required to engage a number
              of different conditions simultaneously.

              I hope this helps.

              . . . . . . . . . . . Ken
              --
            • W. Eliot Kimber
              ... Depending on the complexity of what you re trying to do, it might be easier to implement or maintain either of these options: - Preprocess the input to do
              Message 6 of 8 , Apr 5, 2007
              • 0 Attachment
                G. Ken Holman wrote:

                > Yes, sometimes elaborate predicates are required to engage a number
                > of different conditions simultaneously.

                Depending on the complexity of what you're trying to do, it might be
                easier to implement or maintain either of these options:

                - Preprocess the input to do the filtering to an intermediate document
                and then apply the formatting rules to the intermediate result. This
                then separates the concerns of filtering from the concerns of formatting
                (this is what the DITA Open Toolkit does, for example). You can do this
                all in one style sheet or do it as two separate transforms in a pipeline.

                - Encapsulate the conditional check into one or more functions that both
                hide the details of the check and put the details into one place. This
                is easier in XSLT 2 where stylesheet-defined functions are part of the
                language, rather than an extension as they are in XSLT 1.

                Also, if your predicate statements are long and repeated, you can put
                them into an internal text entity like so:

                <!DOCTYPE xsl:stylesheet [
                <!ENTITY pred1 "this is a really long and gnarly predicate" >
                ]>
                <xsl:stylesheet>
                ...
                <xsl:template match="*[&pred1;]">
                ...
                </xsl:template>
                ...
                </xsl:template>

                Cheers,

                Eliot
                --
                W. Eliot Kimber
                Professional Services
                Innodata Isogen
                8500 N. Mopac, Suite 402
                Austin, TX 78759
                (214) 954-5198

                ekimber@...
                www.innodata-isogen.com
              • mina_hurray
                Thank you for your response. I did try using entity inside the style sheet. Somehow the style sheet is not picking up the entity name. Here is the structure:
                Message 7 of 8 , Apr 23, 2007
                • 0 Attachment
                  Thank you for your response. I did try using entity inside the style
                  sheet. Somehow the style sheet is not picking up the entity name.

                  Here is the structure:

                  <!DOCTYPE xsl:stylesheet [
                  <!ENTITY Grp "document(...)/root/grp" >
                  ]>

                  The document() refereces an external xml file of the structure:

                  <root>

                  <grp>123</grp>

                  </root>


                  I reference this entity using &Grp; on the style sheet. But the style
                  sheet is not recognizing it.

                  Any suggestions will be greatly appreciated.

                  --- In XSL-FO@yahoogroups.com, "W. Eliot Kimber" <ekimber@...> wrote:
                  >
                  > G. Ken Holman wrote:
                  >
                  > > Yes, sometimes elaborate predicates are required to engage a number
                  > > of different conditions simultaneously.
                  >
                  > Depending on the complexity of what you're trying to do, it might be
                  > easier to implement or maintain either of these options:
                  >
                  > - Preprocess the input to do the filtering to an intermediate document
                  > and then apply the formatting rules to the intermediate result. This
                  > then separates the concerns of filtering from the concerns of
                  formatting
                  > (this is what the DITA Open Toolkit does, for example). You can do this
                  > all in one style sheet or do it as two separate transforms in a
                  pipeline.
                  >
                  > - Encapsulate the conditional check into one or more functions that
                  both
                  > hide the details of the check and put the details into one place. This
                  > is easier in XSLT 2 where stylesheet-defined functions are part of the
                  > language, rather than an extension as they are in XSLT 1.
                  >
                  > Also, if your predicate statements are long and repeated, you can put
                  > them into an internal text entity like so:
                  >
                  > <!DOCTYPE xsl:stylesheet [
                  > <!ENTITY pred1 "this is a really long and gnarly predicate" >
                  > ]>
                  > <xsl:stylesheet>
                  > ...
                  > <xsl:template match="*[&pred1;]">
                  > ...
                  > </xsl:template>
                  > ...
                  > </xsl:template>
                  >
                  > Cheers,
                  >
                  > Eliot
                  > --
                  > W. Eliot Kimber
                  > Professional Services
                  > Innodata Isogen
                  > 8500 N. Mopac, Suite 402
                  > Austin, TX 78759
                  > (214) 954-5198
                  >
                  > ekimber@...
                  > www.innodata-isogen.com
                  >
                Your message has been successfully submitted and would be delivered to recipients shortly.