cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
Showing results for 
Search instead for 
Did you mean: 

Community Tip - You can Bookmark boards, posts or articles that you'd like to access again easily! X

How to use XPath expression in Edit APP source in _ufe element?

jhubackova
11-Garnet

How to use XPath expression in Edit APP source in _ufe element?

Hello, I want to use _ufe element with universal definition of the colour.
The actual colour will be set in the xml document, e.g. in the <productname> element and his "role" attribute.

I changed the APP source for _ufe by this way:

...
//var color_value = '#0c6979';
var color_value = formating.evaluateXPath("//productname/@role");

 

// Print/PDF properties
style.color = ( color_value )
...

but it doesnť work. Maybe the formating.evaluateXPath function doesn't return a string value?
The attempt with the direct setting of the color (a commented row) works OK.

 

Thanks for help

Jana

1 ACCEPTED SOLUTION

Accepted Solutions

I haven't done this for a while, but there always used to be problems with XPath in generated content. Essentially the XPath couldn't properly "see" the document tree when running inside the generated content.

 

There are a couple of solutions:

  1. Store the colour value in a variable and use it later on
  2. Try prepending xml0# to the XPath

For #1, you would have to add a source edit in the root element to save the colour value. e.g. application.variables.myColour = formatting.evaluteXPath("/my/xpath"); Then you can use application.variables.myColour in your generated content source edit.

 

For #2, we're trying to trick APP to "see" the correct XML stream. The in-memory APP document will have a number of streams (headers, footers, and main text). The main text used to be called "xml0" hence the special syntax to direct the XPath to the correct location. e.g. formatting.evaluateXPath("xml0#/my/xpath");

View solution in original post

16 REPLIES 16

You will need to read the FOM documents to get the exact return values, although I think formatting.evaluateXPath() should return a string. The fxDocument (DOM) version of evaluateXPath certainly returns an object though. Your code otherwise looks mostly fine and should do what you're after.

 

Ideas:

  1. Check what the result string is: formatting.write( formatting.evaluteXPath("/whatever") );
  2. Don't use // at the start of an XPath expression. This causes the formatter to search the *entire* document everytime and slows formatting/printing down. Instead you should use a direct path e.g. /document/path/to/productname/@role

Hi Gareth, thanks for your tip,  I checked the expression and it returns correct value (e.g. in generated text). But whenever I use it in the APP source edit it doesn't work. The colour of the text is stil in black or it doesn't appear at all.

Jana

 

XPath in APP source.png

Hello, I found the different behaviour - whenever I use this _ufe element (with xpath expression) in the common text it works correctly. 

But when I use this same _ufe element  in the "Generated Contents" in the Page Region (and it is area when I need it 🙂 it doesn't work at all.  

Do you have any idea how to solve it?  Sorry I'm not very skill in FOM/DOM syntaxe ...

 

Thanks  Jana

 

 

I haven't done this for a while, but there always used to be problems with XPath in generated content. Essentially the XPath couldn't properly "see" the document tree when running inside the generated content.

 

There are a couple of solutions:

  1. Store the colour value in a variable and use it later on
  2. Try prepending xml0# to the XPath

For #1, you would have to add a source edit in the root element to save the colour value. e.g. application.variables.myColour = formatting.evaluteXPath("/my/xpath"); Then you can use application.variables.myColour in your generated content source edit.

 

For #2, we're trying to trick APP to "see" the correct XML stream. The in-memory APP document will have a number of streams (headers, footers, and main text). The main text used to be called "xml0" hence the special syntax to direct the XPath to the correct location. e.g. formatting.evaluateXPath("xml0#/my/xpath");

Hi Gareth, many thanks,  #1 solution (application.variables) works perfect for the Generated Content in the title page!

 

I tried to test also your #2 tip by using XML streams.

But I donť know how to find out the correct number of the stream for the using in my XPath expression?

 

J.

Yes this isn't particularly obvious or easy to get to. The most straightforward way would be to use the Styler option that lets you save a .3D file to disk. The .3D file is an intermediate format that contains the complete set of content and styling used to produce the PDF. You can then open the .3D file in a text editor (e.g. Notepad++) and find all the stream definitions (fdt "streamName"). If you spend five minutes poking around in that file it should be pretty obvious which one is the main content stream.

Hi Gareth,

 

I also ran into same situation as Jana. I have used solution #1 and did work, but I would like to try solution #2 as well. The difference is that i would like to use an XPath function like count() within the XPath expression.

 

I have tried the following with no success:

 

var NoPubs = formatting.evaluateXPath("count(xml0#//chghistory/chginfo) + 1");

and

var NoPubs = formatting.evaluateXPath("count(xml0#/chghistory/chginfo) + 1");

 

document root is <doc>, and the absolute path to the nodeset  is doc/docwp/front/idinfo.

What i am doing wrong?

I would appreciate any help.

 

Florin

Start with a simple expression and grow from there.

 

formatting.evaluateXPath("count(/doc)"); // should return "1", unless your XPath context is not the main stream

formatting.evaluateXPath("count(xml0#/doc)"); // should return "1", forcing XPath context to main stream

 

If neither of the above are working then you will need to figure out what the main stream name is, by opening a .3D file and inspecting with a text editor. Sorry but I haven't done this for a few years now so I'm not up to date on exact stream names and things.

 

Hi Gareth,

 

It did not work, most likely because the xml0# is not the main stream name.

I never used (create, access, or access) a .3d file.

 

Any help to get #2 working is appreciated. like I said #1 works just fine but now you made me curios how #2 can be implemented.

 

Thank you for help!

 

Florin

 

 

Hi Florin, the .3d file you can create by these steps: from Styler menu - Preview - Print - and then from APP Preview window - File - Save APP File.

 

But despite Gareth's instruction I was not able to find the correct XML stream for the #2 solution, so I used the #1 one. Anyway I'm interested if you will be more successful. If so, post your method.

 

Thanks Jana

otudor
8-Gravel
(To:otudor)

Hi Gareth,

Followed Jana's instructions to create the .3d file, thank you Jana, and I did poke around with the file looking for all (1657) fdt "name" that could resemble anything close to a stream name but with no success.

 

However, poking around I found something that caught my eye, namely this lines 

$template.primaryStream = 'editorDom0';

$application.variables['_x_primaryStream'] = 'editorDom0';

under the following fdt line, fdt "autoexec",90,"",0,"";;4.

 

I have tried all the following with no success:

formatting.evaluateXPath("count(editorDom0#//doc")

formatting.evaluateXPath("count(editorDom0#/doc")

formatting.evaluateXPath("count(editorDom0//doc")

formatting.evaluateXPath("count(editorDom0/doc")

and that made me think that editorDom0 is not the main stream I am looking for.

 

I still want to get this solution working because more direct (1 step deal) than the second solution which uses two step process. Like I said #1 work just fine.

 

Am I looking at the wrong thing? Any other suggestion or tip?

 

Thank you for help!

 

Have a blessed day!

 

Florin

You're correct it is "editorDom0" that is the main stream for Styler-generated the .3D files. I had forgotten. I tested in a standalone .3D file and the syntax formatting.evaluateXPath("editorDom0#/doc"); is the correct one. Perhaps you should raise this with PTC support for further assistance.

Hi Gareth,

 

After posting the previous post I kept poking around with the .3d file and I found the following peace of code (changes are obvious :)) that confirms that editorDom0 is the main stream:

 

var florin = content.getStream(template.primaryStream);

application.alert("steram name: " + florin.name);

 

which produces the attached result.

 

Now that Gareth confirmed too that editorDom0 is the main stream I will try again to evaluate the XPath, and if does not work I will reach PTC like Gareth suggested.

Jana, you can also try it and see what results are you getting.

 

Thank you for help!

 

Florin

Hi Florin,  here is one PTC Article concerning our thema 🙂

https://www.ptc.com/en/support/article?n=CS22760

They use this trick:

Change:
if ( formatting.evaluateXPath( "@xml:lang = 'ja'", "1if1" ) != 0 )
To:
if ( formatting.evaluateXPath( "editorDom0#boolean( /RDStyle/ResolvedMap/shopmanualmap/@xml:lang = 'ja')", "1if1" ) != 0 )

 

 

 

Hi Jana,

 

Thank you for pointing me in the right direction. After I tried to see what makes sens for me from all that, I came up with following syntax that did work for me.

 

Looking for text() node:

formatting.evaluateXPath("editorDom0#//your/XPath/expression/here/text()", "1if1"));

Using an XPath function:

formatting.evaluateXPath("editorDom0#count(//your/XPath/expression/here)", "1if1"));

Important notes:

 

1. I have tried "editorDom#/your/XPath/expression/here" with one forward slash instead of two forward slashes in the XPath expression and did not work. I know, I know... PTC recommends not to use double forward slashes in a XPath expression because slows down the process, and I kind of agree with that, but this is my finding for now. Gareth, any input?

 

2. Another finding is that the above expressions won't give the expected result without the second parameter "1if1", which to be honest I do not know what it means and/or what it does. Gareth, any input? So do not forget to add "1if1" as a second parameter for evaluateXPath() function. I have looked up in PTC Help, and evaluateXPath() function in fFormatting interface takes only an expression parameter, not two.

 

Thank you again Gareth and Jana to help me get this much more elegant solution to work.

 

Have a blessed day!

 

Florin

1. I think the problem is that what you're styling isn't what you expect. Note in that PTC Article there is a /RDStyle/... in the path, that is why you need double-slash so it navigates past that extra element. The problem with // is that it will slow your publishing down - it forces APP to visit every node in the entire document each time that XPath is evaluated.

 

2. I have no idea about "1if1", this is the first time I've ever seen that syntax.

Top Tags