How namespaces in XML and FreeMarker template work together? - dom

I have read a few relevant topics on here and now have a basic understanding of the namespace concept. But I still have some difficulties getting my template to work with my XML data.
When there is no namespace involved, this template and this XML works fine:
ftl:
${pp.doc.user1.name}
XML:
<?xml version="1.0" encoding="UTF-8" ?>
<user1>
<name>Jack</name>
</user1>
However, if there is namespace defined in the XML file, like this:
<?xml version="1.0" encoding="UTF-8" ?>
<user1 xmlns="https://example.com/xyz">
<name>Jack</name>
</user1>
I got error messages:
Error when processing this file: data\test1.xml
FreeMarker template error: For "${...}" content: Expected a string or something automatically convertible to string (number, date or boolean), or "template output" , but this has evaluated to a sequence+hash (wrapper: f.e.dom.NodeListModel):
==> pp.doc.user1.name [in template "renderer/test.ftlh" at line 1, column 3]
----
Tip: This XML query result can't be used as string because for that it had to contain exactly 1 XML node, but it contains 0 nodes. That is, the constructing XML query has found no matches.
----
----
FTL stack trace ("~" means nesting-related):
- Failed at: ${pp.doc.user1.name} [in template "renderer/test.ftlh" at line 1, column 1]
----
My current understanding is that in the ftl, I need to use <#ftl ns_prefixes={"ns": "https://example.com/xyz"}> or something like this, but none of the things I tried have worked. Please kindly help. Thank you!

In pp.doc.user1.name you aren't using any namespace prefix, so the elements are assumed to belong to the default namespace, which is by default nothing. To set it, use <#ftl ns_prefixes={"D": "https://example.com/xyz"}>. D is a prefix reserved for this purpose.

Related

Powershell reading from a XML

I am attempting to read from an XML file and make an output of the information.
<?xml version="1.0" encoding="utf-8"?>
<ModelList>
<Model name="ThinkCentre M715Q">
<Types>
<Type>10M4</Type>
<Type>10RA</Type>
<Type>10RB</Type>
<Type>10M5</Type>
<Type>10RC</Type>
<Type>10M2</Type>
<Type>10RD</Type>
<Type>10M3</Type>
</Types>
</Model>
</ModelList>
I managed to get the output of the model attribute with the following powershell code.
[xml]$xmlFile = Get-Content -Path C:\Temp\data.xml
$xmlFile.GetType().Attributes
$xmlFile.ModelList.Model | Format-Table
Output information with the current code above:
name Types
---- -----
ThinkCentre M715Q Types
But... As you can see, the Types attribute is just types. I also want to be able to read the nested information inside of the ModelList. I want the output to be more like this:
name Types
---- -----
ThinkCentre M715Q 10M4, 10RA, 10RB, 10M5, 10RC...
I am stuck here. I need guidance to just simply bind the attributes. That Types attribute knows it is associated with the Model of ThinkCentre. Any help is appreciated! Thanks.
Since your XML could contain more models and types, you would need to loop over the nodes.
Also, there is a better way to load the xml than using Get-Content that automatically takes the documents encoding into account:
# load the xml file. This way, you are ensured to get the file encoding correct
$xml = [System.Xml.XmlDocument]::new()
$xml.Load('C:\Temp\data.xml')
foreach ($model in $xml.ModelList.Model) {
[PsCustomObject]#{
Model = $model.Name
Types = $model.Types.Type -join ', '
}
}
Output:
Model Types
----- -----
ThinkCentre M715Q 10M4, 10RA, 10RB, 10M5, 10RC, 10M2, 10RD, 10M3

JBoss CLI: add a nested element within an element without name attribute (adding "key" element inside "jwt")

Generally speaking, I am trying to add a nested element inside another one, where the parent element does not contain a name attribute:
<parentElement name="fooName">
<foo property1="abc"/>
</parentElement>
should become:
<parentElement name="fooName">
<foo property1="abc">
<fooChild property2="bcd"/>
</foo>
</parent>
The problem with this is that I cannot find a way to properly build the path for the CLI command:
/sybsystem=xxx/parentElement=fooName/foo:add(fooChild={property2="bcd"})
gives me an error Node path format is wrong around 'foo' (index=37).
I assume this is because the foo element doesn't have an attribute name.
More specifically I am looking for a way to add key element inside the jwt element:
<token-realm name="jwt-realm" principal-claim="sub">
<jwt issuer="${JWT_ISSUER}" audience="${JWT_AUDIENCE}" public-key="${JWT_PUBLIC_KEY}"/>
</token-realm>
should become:
<token-realm name="jwt-realm" principal-claim="sub">
<jwt issuer="${JWT_ISSUER}" audience="${JWT_AUDIENCE}" public-key="${JWT_PUBLIC_KEY}">
<key kid="xxx" public-key="${JWT_PUBLIC_KEY}"/>
</jwt>
</token-realm>
The command I am trying to use:
/subsystem=elytron/token-realm=jwt-realm/jwt:add(key={kid="xxx",public-key="${JWT_PUBLIC_KEY}"})
and the error I get: Node path format is wrong around 'jwt' (index=41).
Thanks to my outstanding colleague (he hasn't got an account here, shame), the answer has been found.
To update the key's map the following command can be used:
/subsystem=elytron/token-realm=jwt-realm:write-attribute(name=jwt, ... ,key-map={"xxx","${JWT_PUBLIC_KEY}"}})
(... here the list of other standard attributes of the jwt element).

Unable to unit test an XSLT template rule that generates an element with nested elements

I have an XSLT template that transforms this:
<WGS__LAT>N20340000</WGS__LAT>
to this:
<latitude>
<deg>20</deg>
<min>34</min>
<sec>00</sec>
<hSec>00</hSec>
<northSouth>North</northSouth>
</latitude>
I wrote an XSpec scenario to test the XSLT template:
<x:scenario label="location/latitude: Check that the XSLT assigns latitude the split-up value of WGS__LAT">
<x:context>
<WGS__LAT>N20340000</WGS__LAT>
</x:context>
<x:expect label="Expect: deg=20, min=34, sec=00, hSec=00, northSouth=North">
<latitude>
<deg>20</deg>
<min>34</min>
<sec>00</sec>
<hSec>00</hSec>
<northSouth>North</northSouth>
</latitude>
</x:expect>
</x:scenario>
I am certain that my XSLT template works correctly, so why does the XSpec tool report FAILED? I thought it might have something to do with whitespace in <x:expect> so I removed all whitespace:
<x:expect label="Expect: deg=20, min=34, sec=00, hSec=00, northSouth=North">
<latitude><deg>20</deg><min>34</min><sec>00</sec><hSec>00</hSec><northSouth>North</northSouth></latitude>
</x:expect>
Unfortunately, I still get FAILED. What am I doing wrong?
Without having the full report, and especially what you actually get, it's difficult to answer. But :
in that case, a going starting point is to wrap your context in another tag, and to set in the xspec which part of the result should match. Something like :
<x:context>
<foo>
<WGS__LAT>N20340000</WGS__LAT>
</foo>
</x:context>
<x:expect label="..." test="/foo/*" as="element(latitude)">
<latitude>
<deg>20</deg>
<min>34</min>
<sec>00</sec>
<hSec>00</hSec>
<northSouth>North</northSouth>
</latitude>
</x:expect>
You may have a look at wiki for more precise use of expectations.
Then, actual result and expected result are compared with fn:deep-equals(...) method. And so, there is no output processing on result or on expect. Il you use an #href on x:context or on x:expect, then there is a space-normalization, but I'm not perfectly sure of that.
You may have a look at this issue on indentation problems ; it's a quite long and still open thread.

Define class hierarchy in Notation 3

I am trying to develop a simple Notation3 ontology file.
so far my code in the notation3 file is
#prefix my: <http://www.codeproject.com/KB/recipes/n3_notation#>.
#prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
#prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
my:batterycs a my:spec;
my:preferedby my:BusinessPerson, my:LoveBird, my:MusicLover, my:Travelar;
my:name "batteryCS".
rdfs:Person a rdfs:Class.
I am using dotNetRdf library to read and query the ontology file. the above code in n3 file works fine. But when I Insert
rdfs:Woman a rdfs:Class; rdfs:subClassOf :Person .
at the end of the ontology file it occurs the error Unable to resolve the QName ':Person' seems like it cant even load the ontology to the parser.
I studied the n3 syntax from http://www.w3.org/2000/10/swap/Primer.html
can somebody help me with this where I have made the mistake
thanks in advance
Your data is invalid, you need to define the empty prefix in order to be able to refer to it in a QName such as :Person
A QName (Qualified Name) is a syntactic shortcut which allows you to shorten URIs written in the form prefix:name where prefix must refer to a defined namespace prefix defined via a previous #prefix statement. The parser then simply looks up the prefix and concatenates it with the name part, so for example rdfs:Class is expanded to http://www.w3.org/2000/01/rdf-schema#Person in your example data.
If a prefix is not defined then a RDF parser is expected to throw an error.
So you need to fix your data, there are a couple of ways to do this depending on what your intent was.
You meant to put :Person in your own my: namespace
Simply replace :Person with my:Person
Note that you have also referred to rdfs:Person so your data looks somewhat inconsistent
You meant to defined an empty namespace
Simply add the following #prefix definition:
#prefix : <http://example.org/namespace#> .
Where the URI is the desired namespace URI
Aside
What version of dotNetRDF are you using? And is the error message you quote the complete error message?
More recent versions of dotNetRDF are supposed to give more informative error messages that should have told you that you were likely missing a prefix declaration

parsing xml having multiple namespaces using xml::Libxml::Xpathcontext in perl

I have to parse following XML:
<reply xmlns="urn::ietf::param" xmlns:element="https://xml.example.net/abc/12.3"
message-id='1'>
<abc>
<xyz> hello </xyz>
</abc>
</reply>
I want the value of xyz node i.e. hello, but findnodes is returning null value.
my code is :
my $xpath=XML::LibXML::XPathContext->new($dom);
$xpath->registerNs('ns1','urn::ietf::param');
$xpath->registerNs('ns2','https://xml.example.net/abc/12.3');
$val=$xpath->findnodes('//ns1:reply/ns2:element/abc/xyz');
print $val;
but print statement is returning null value
It looks like you have some misunderstanding about how namespaces work. xmlns:element="https://xml.example.net/abc/12.3" means that there is a prefix element defined with this specific namespace URI. This namespace is actually never used in your XML.
xmlns="urn::ietf::param" defines a default namespaces and also applies to all descendant elements.
And actually you have no <element/> element in your XML.
Thus, the following XPath should work as expected:
//ns1:reply/ns1:abc/ns1:xyz