12 Replies Latest reply on Apr 27, 2011 6:26 AM by John Hawkinson

    c#: Get xml element associated with tag/textframe

    xmlapi Level 1

      I have a text frame that is tagged as "XmlFrame1" and in it there's "xmlitem1" and "xmlitem2" etc.

       

      I want to iterate through the pages and get this tag's text on each page:

       

      In c#:

      foreach(Page page in document.Pages)
      {

         TextFrame textFrame = page.TextFrames.FindItems("textFrame1");

          XmlItem xmlFrame1 =   textFrame.AssociatedXMLElement;  //This throws an error: Return argument has an invalid type (InvalidCastException)

      }

       

       

      In javascript, I used to be able to do this:

      for( i=0 ; i < templateDoc.pages.length ; ++i )
      {
              var page = templateDoc.pages.item(i);
                var textFrame = page.textFrames.findItems({ label:  'textFrame1' })[0];
               if( textFrame != null && textFrame.associatedXMLElement != null)
               {
                  var xmlItem1= textFrame.associatedXMLElement.evaluateXPathExpression("//xmlItem1")[0];

                  var xmlItem2= textFrame.associatedXMLElement.evaluateXPathExpression("//xmlItem2")[0];

               }

      }

       

      Why isn't it working in c#?

        • 1. Re: c#: Get xml element associated with tag/textframe
          MatthewMariani Level 1

          I don't know about C# but there was prior discussion about how obtaining a reference to an object by a scripting label has changed in CS5: If you are running CS5, this JavaScript might work:

           

          var templateDoc= app.documents[0];
          for( i=0 ; i < templateDoc.pages.length ; ++i )
          {
             var page = templateDoc.pages.item(i);
             app.scriptPreferences.version = "6.0"
             var textFrame = page.textFrames.item('textFrame1').getElements()[0];
             app.scriptPreferences.version = "7.0"
             if( textFrame != null && textFrame.associatedXMLElement != null)
               {
                 var xmlItem1= textFrame.associatedXMLElement.evaluateXPathExpression("//xmlItem1")[0];
                 var xmlItem2= textFrame.associatedXMLElement.evaluateXPathExpression("//xmlItem2")[0];
               }
          }
          

          • 2. Re: c#: Get xml element associated with tag/textframe
            xmlapi Level 1

            I already have the code for JS but unfortunetly, the project has to be written in C#. I did the code conversion but everytime I refer to the property AssociatedXMLElement, the property throws an invalid cast exception.

             

            Is there anyway to get the "xml tag" associated with a textframe/page?

            • 3. Re: c#: Get xml element associated with tag/textframe
              John Hawkinson Level 5
              I already have the code for JS but unfortunetly, the project has to be written in C#. I did the code conversion but everytime I refer to the property AssociatedXMLElement, the property throws an invalid cast exception.

              Yes, this is expected behavior, as was already mentioned. In CS5, .item() now searches on the name not the label. Presumabing that your C# FindItems() method does the same thing, it is now searching the name, not hte label. To search with the label, you need to iterate over all items and compare the label explicitly.

               

              Since you set textFrame with FindItems(), if your FindItems() method doesn't work, then your textFrame will not work.

              • 4. Re: c#: Get xml element associated with tag/textframe
                cweger79 Level 1

                John,

                 

                I don't think that's his problem. I tried this:

                 

                            InDesign.Application idApp = new InDesign.Application();
                            Document d = idApp.Documents.FirstItem();
                            TextFrame myFrame = d.Pages.FirstItem().TextFrames.FirstItem();
                            string frameContents = myFrame.Contents;
                            System.Console.WriteLine("contents = {0}", frameContents ); // just to make sure we have a frame
                            object foo = myFrame.AssociatedXMLElement;  //This throws an error: Return argument has an invalid type (InvalidCastException)

                 

                So it's not that he's not finding the textFrame, there's something else going on.

                 

                Regards,

                Chuck

                 

                PS: I should note that the same exact code (different syntax, of course) works fine in ExtendScript.

                • 5. Re: c#: Get xml element associated with tag/textframe
                  Dirk Becker  Level 4

                  Chuck,

                   

                  now that you have your TLB, could you have a look at the type of AssociatedXMLElement?

                   

                  The issue reminds me of an old forum thread, watch out for "LateBinding" and "ilasm" in ...

                  http://forums.adobe.com/message/1106030

                   

                  Regards,

                  Dirk

                  • 6. Re: c#: Get xml element associated with tag/textframe
                    cweger79 Level 1

                    Hi Dirk,

                     

                    The VS2010 Object Browser says that its type is "InDesign.XMLItem"

                     

                    However, if I put in a breakpoint and try to look at the textFrame, when the Locals window gets to the "associatedXMLElement" property, it says:

                     

                    AssociatedXMLElement    '(myFrame).AssociatedXMLElement' threw an exception of type 'System.InvalidCastException'    InDesign.XMLItem {System.InvalidCastException}

                     

                    So that property is not really what Visual Studio thinks it should be.

                     

                    I suspect this is a bug. I also suspect that there's nothing that can be done about it, since Adobe doesn't support Visual C#. Which in my opinion is kind of strange, since C# seems to be the language of choice for many Windows developers these days. Not that I want to grow up to be a Windows developer, of course....

                     

                    Regards,

                    Chuck

                    • 7. Re: c#: Get xml element associated with tag/textframe
                      John Hawkinson Level 5

                      I don't really know much about visual studio, but can you try casting it to another type? Do AssociatedXMLElements work properly on other kinds of objects? can that give you a hint?

                       

                      Also, can't you access the VBScript interface from C# somehow? At worst via doScript [but surely there's a better COM mechanism?].

                       

                      Anyhow, in re:

                       

                      I also suspect that there's nothing that can be done about it, since Adobe doesn't support Visual C#. Which in my opinion is kind of strange, since C# seems to be the language of choice for many Windows developers these days.

                      Remember, Adobe's scripting is not for developers. It is really for end-users. And they are already supporting 3 different languages, which is a significant burden. (Maybe Ole Kvern can give some insight now that he has left Adobe Systems?).

                       

                      They really need to support something platform-independent, so that's JavaScript. They need to support the OS-native scripting support for each OS because users need to integrate InDesign with other apps on the same machine, so that's AppleScript on the Mac. You would know better, but on Windows, isn't VBScript still the language of choice for end-users who want to script little bits of functionality?

                       

                      Unless that were to change (and it seems to me unlikely to change to C#!), I think they have to support VBScript.

                       

                      Adding a 4th language in the mix doesn't seem like it's going to happen. But ideally the APIs should be aligned so this isn't an issue. But I don't know anything about COM, so...

                      • 8. Re: c#: Get xml element associated with tag/textframe
                        John Hawkinson Level 5

                        Oh, also: this is not about an XMLItem versus and XMLElement type, is it? Since you mentioned the locals window I think the answer is no, but...

                        • 9. Re: c#: Get xml element associated with tag/textframe
                          cweger79 Level 1

                          Hi John,

                           

                          In answer to your first post, yes, you can access the COM stuff from C#; there's only one TLB (Type Library) file, and it can be used by most .NET languages, I believe. And I suppose you're right about scripting being for "end users" although I've met precious few end users who can actually script. Usually it's developers who (like me) are slumming who do the heavy scripting.

                           

                          And I agree that Adobe has too much on their plate to add another language. However, this exact problem will also show up in VBScript, since that's using the same COM type library. So I guess it could be reported as a bug.

                           

                          Off Topic: if it were up to me, I would cancel VB and AppleScript support, and spend some time beefing up the JavaScript implementation (can anyone say "string formatting"? How about "web services that you don't have to roll yourself"?) along with better out-of-app communication (for example, a better "do script" that has a cleaner interface in both directions). But luckily or unluckily, it's not up to me.

                           

                          Anyway, no, it's not about XMLItem vs XMLElement; the fact that it crashes in the debugger locals window means Windows can't figure out what type the result is, which is a Bad Thing.

                           

                          Regards,

                          Chuck

                          • 10. Re: c#: Get xml element associated with tag/textframe
                            John Hawkinson Level 5

                            Hey, Chuck.

                             

                                  Well, I'd recommend you try it in VBScript then. Not only because it's supported, but also because it's a lot less strongly typed than C#, right? So it's possible that it just works there? And if so, perhaps you can fix it with a cast. Or worst case call out to VB (or JS!) from C#. I was under the impression that this stuff all had a common infrastructure inside InDesign, so it's weird that it would fail for VB but work for JS. Not that there's some rule that bugs can't be weird

                             

                                The problem with scrapping VB is all the people who use, say, VB to tie together an Excel spreadsheet and an InDesign layout. You can certainly script with two different scripts and struggle to find a way to tie them together, but it would be an inelegant and awkward struggle. So I think they're right to want VB to stay.

                             

                                But web would be the way to sell it -- if it makes web publishing work better, then it looks like it has a chance of getting into CS6. If it's not a feature that improves web/epub/tablet/flash/interactive documents, though...good luck?

                            • 11. Re: c#: Get xml element associated with tag/textframe
                              cweger79 Level 1

                              Hi John,

                               

                              Yes, it works (as expected) in VBS because VBS could care less about types. You could probably pass it a FORTRAN array and it would be fine.

                               

                              Anyway, I don't really need to do this at all. I only ever code in ExtendScript because, even though I love AppleScript, these days I'm a cross-platform kind of guy.

                               

                              I was just trying to help out xmlapi with his (her?) question, since I was looking to procrastinate to avoid real work.

                               

                              Anyway, the short answer to the original post seems to be "you can't get there from here."

                               

                              Regards,

                              Chuck

                              • 12. Re: c#: Get xml element associated with tag/textframe
                                John Hawkinson Level 5

                                Well, I guess it shows I'm an idealist, since my short answer is more like: "You can do it, but it hurts!"

                                 

                                1) xmlapi can probably use the solution Dirk pointed to: decompile the TLB and edit the types and rebuild it. Not exactly robust.

                                 

                                2) xmlapi can call either VBScript from C# via some COM mechanism or can use doScript and call either VBScript or ExtendScript through InDesign.