SFNode field in Proto - x3d

I've got these DEFs in my X3D file:
<ImageTexture DEF="texture1" URL="some/image1.png" />
...
<ImageTexture DEF="texture2" URL="some/image2.png" />
I wish to USE these in my ProtoInstances so that I don't have to create a texture node for each (with the corresponding http request for each), by referencing them by name in one of the proto fiels. Something like this:
<ProtoDeclare name="myProto">
<ProtoInterface>
<field name="texture" type="SFString" accessType="initializeOnly" />
</ProtoInterface>
<ProtoBody>
...
<!-- obviously this doesn't work, but you get the idea: -->
<ImageTexture USE="${texture}" />
...
</ProtoBody>
</ProtoDeclare>
...
<ProtoInstance name="myProto">
<FieldValue name="texture" value="texture1" />
</ProtoInstance>
I have tried with IS within the proto set to the one already defined, but it doesn't work for me:
<ProtoDeclare name="myProto">
<ProtoInterface>
<field name="texture" type="SFNode" accessType="initializeOnly" />
</ProtoInterface>
<ProtoBody>
...
<Appearance>
<IS><connect nodeField="texture" protoField="texture"/></IS>
</Appearance>
...
</ProtoBody>
</ProtoDeclare>
...
<ProtoInstance name="myProto">
<FieldValue name="texture">
<ImageTexture USE="texture1" />
</FieldValue>
</ProtoInstance>
I have also tried with a Script, but cannot find a way to make the link.
Any ideas are very welcome. Thanks!

The IS solution does work. My problem was a different one. The url of my textures was not properly written. Texture url is a MFString, so I had to enclose the value in additional single quotes, like this:
<ImageTexture DEF="texture1" URL='"some/image1.png"' />
...
<ImageTexture DEF="texture2" URL='"some/image2.png"' />
Note that at least in my case, with X_ITE as the browser, using quotes the other way round (double quotes around single quotes) did not work.

Related

XML Value buried inside the node

I'm brand new to XML, but not SQL. I have data structured by our app vendor as follows that I'm trying to load up into a table:
<windowsets>
<windows>
<question>
<id Value="81b25d-9385-sk3" />
<displayname Value="Thermal Break" />
<answername Value="Yes" />
</question>
<question>
<id Value="73v32k-2743-fd9" />
<displayname Value="Panel Profile" />
<answername Value="Medium Stille" />
</question>
</windows>
</windowsets>
Through other posts here I found and got as far as creating:
select
t.x.value('(id [#Value]/text())[1]','varchar(100)') QuestionID,
t.x.value('(displayname [#Value]/text())[1]','varchar(255)') DisplayName,
t.x.value('(answername [#Value]/text())[1]','varchar(255)') AnswerName
from #xmlData.nodes('//windowsets/windows/question') as T(X)
But it returns nulls for all columns, and I'm guessing that's because it's expecting the format of:
<displayname>Panel Profile</displayname>
So being the XML novice and all the searching I've done hasn't help me understand how to change the code to pull it when the value is buried in node (not even sure of correct terminology I'm so new).
THANK you for your help!
It is called attributes.
To read attributes from xml try something like this
select
t.x.value('(id/#Value)[1]','varchar(100)') QuestionID,
t.x.value('(displayname/#Value)[1]','varchar(255)') DisplayName,
t.x.value('(answername/#Value)[1]','varchar(255)') AnswerName
from #xmlData.nodes('//windowsets/windows/question') as T(X)
This is not an new answer, just some explanation and to much for a comment:
The part within the square brackets is called predicate and is kind of a filter. Your expression
displayname [#Value]/text())[1]
will read the text() of <displayname> and will check, if the attribute #Value exists. Anyway, there is no element's text, so it will return NULL.
You must navigate down the path like .../displayname/#Value if you want to read the attribute's value.
This answer shows some examples how XML deals with empty members.

determine issued rowCommand by command name

I have two row commands running on a gridpanel like the following:
<ext:CommandColumn>
<Commands>
<ext:GridCommand Icon="NoteEdit" CommandName="mailEdit">
<ToolTip Text="Edit" />
</ext:GridCommand>
<ext:GridCommand Icon="ApplicationLightning" CommandName="mailChangeBlock">
<ToolTip Text="block/unblock" />
</ext:GridCommand>
</Commands>
</ext:CommandColumn>
now i listen to these row commands:
<Listeners>
<Command Handler="if(command == 'mailEdit'){mailEdit}else{mailChangeBlock}; console.log(command);"/>
</Listeners>
another try was following:
<Command Handler="(command == 'mailEdit') ? mailEdit : mailChangeBlock;" />
the console log is executed without problems, but a console.log in the function called is not executed, even though the function gets called as soon as you add brackets to each call, but then the data passed to the function is lost.
my question is now, how can i determine which command was executed and call a corresponding function and give value, metadata and record to it?
It is possible to send the Command name and other values by Extra Params:
<DirectEvents>
<Command OnEvent="GridCommand">
<ExtraParameters>
<ext:Parameter Name="commandname" Value="command" Mode="Raw" />
<ext:Parameter Name="recordid" Value="record.data.id" Mode="Raw" />
</ExtraParameters>
</Command>
</DirectEvents>
the determination of command can then be executed server-sided (command returns the CommandName defined in the CommandColumn) and then execute server-sided script.

Ant: Find the path of a file in a directory

I want to find the path of a file in a directory (similar to unix 'find' command or the 'which' command, but I need it to work platform-independent) and save it as a property.
Tried to use the whichresource ant task, but it doesn't do the trick (I think it's only good for looking inside jar files).
I would prefer if it would be pure ant and not to write my own task or use a 3rd-party extension.
Notice that there might be several instances of a file by that name in the path - I want it to only return the first instance (or at least I want to be able to choose only one).
Any suggestions?
One possibility is to use the first resource selector. For example to find a file called a.jar somewhere under directory jars:
<first id="first">
<fileset dir="jars" includes="**/a.jar" />
</first>
<echo message="${toString:first}" />
If there are no matching files nothing will be echoed, otherwise you'll get the path to the first match.
Here is an example which selects the first matching file. The logic is as follows:
find all matches using a fileset.
using pathconvert, store the result in a property, separating each matching file with line separator.
use a head filter to match the first matching file.
The functionality is encapsulated in a macrodef for reusability.
<project default="test">
<target name="test">
<find dir="test" name="*" property="match.1"/>
<echo message="found: ${match.1}"/>
<find dir="test" name="*.html" property="match.2"/>
<echo message="found: ${match.2}"/>
</target>
<macrodef name="find">
<attribute name="dir"/>
<attribute name="name"/>
<attribute name="property"/>
<sequential>
<pathconvert property="#{property}.matches" pathsep="${line.separator}">
<fileset dir="#{dir}">
<include name="#{name}"/>
</fileset>
</pathconvert>
<loadresource property="#{property}">
<string value="${#{property}.matches}"/>
<filterchain>
<headfilter lines="1"/>
</filterchain>
</loadresource>
</sequential>
</macrodef>
</project>
I created a macro based on martin-clayton's answer.
sample project with macro and a property file that is read from the found file
<?xml version="1.0" encoding="utf-8"?>
<project name="test properties file read" default="info">
<macrodef name="searchfile">
<attribute name="file" />
<attribute name="path" default="custom,." />
<attribute name="name" />
<sequential>
<first id="#{name}">
<multirootfileset basedirs="#{path}" includes="#{file}" erroronmissingdir="false" />
</first>
<property name="#{name}" value="${toString:#{name}}" />
</sequential>
</macrodef>
<searchfile name="custom.properties.file" file="config.properties" />
<property file="${custom.properties.file}" />
<target name="info" >
<echo>
origin ${config.origin}
</echo>
</target>

defining array variable in web-harvest

I'm using Web-Harvest to extract some data from a site.
Site gets a POST variable named Code and gives data according to it.
The available codes are gathered from another page of that site.
How Can I define an array like variable to store those data that are related to a Code in a array like variable that make me able to retrieve them with a loop in main program?
I mean something like this:
Data[code1]={key1=val1, key2=val2, key3=val3,...}
Data[code2]={key1=val1, key2=val2, key3=val3,...}
Data[code3]={key1=val1, key2=val2, key3=val3,...}
Data[code4]={key1=val1, key2=val2, key3=val3,...}
...
You can use <script> tag and build an array inside it using BeanShell, Groovy or JavaScript. Default is BeanShell.
Then expose it to your script with SetContextVar() method or return attribute of the <script>.
Below is example that builds an array of strings codes and then iterates through them with <loop>.
<?xml version="1.0" encoding="UTF-8"?>
<config>
<script><![CDATA[
String[] codes = new String[] {"one", "two", "three"};
SetContextVar("codes", codes);
]]></script>
<loop item="code">
<list>
<var name="codes" />
</list>
<body>
<var name="code" />
</body>
</loop>
</config>
Read more about <script> in the Web-Harvest manual.

Solr DataImportHandler: Can I get a dynamic field name from xml attribute with XPathEntityProcessor?

I have some XML to ingest into Solr, which sounds like a use case that is intended to be solved by the DataImportHandler. What I want to do is pull the column name from one XML attribute and the value from another attribute. Here is an example of what I mean:
<document>
<data ref="reference.foo">
<value>bar</value>
</data>
</document>
From this xml snippet, I want to add a field with name reference.foo and value bar. The DataImportHandler includes a XPathEntityProcessor for processing XML documents. I've tried using it and it works perfectly if I give it a known column name (e.g, <field column="ref" xpath="/document/data/#ref">) but have not been able to find any documentation or examples to suggest either how to do what I want, or that it cannot be done. So:
Can I do this using XPathEntityProcessor? If so, how?
If not, can I do this some other way with DataImportHandler?
Or am I left with writing my own import handler?
I haven't managed to find a way to do this without bringing in a transformer, but by using a simple ScriptTransformer I worked it out. It goes something like this:
...
<script>
function makePair(row) {
var theKey = row.get("theKey");
var theValue = row.get("theValue");
row.put(theKey, theValue);
row.remove("theKey");
row.remove("theValue");
return row;
}
</script>
...
<entity name="..."
processor="XPathEntityProcessor"
transformer="script:makePair"
forEach="/document"
...>
<field column="theKey" xpath="/document/data/#ref" />
<field column="theValue" xpath="/document/data/value" />
</entity>
...
Hope that helps someone!
Note, if your dynamicField is multivalued, you have to iterate over theKey since row.get("theKey") will be a list.
What you want to do is select the node keying on an attribute value.
From your example, you'd do this:
<field column="ref" xpath="/document/data[#ref='reference.foo']"/>

Resources