I recognize your problem. I mitigate it by some preprocessing (in an
XProc pipeline, but anything else will do).
In the preprocessing, I turn the value of the @key attribute into the
element's name (supposing it is a NCName) and add a type attribute to
reflect that it was an array, a map, a string, etc.. For elements that
don't have a key, I include the name of the parent in the element name
that I generate. That does not cover everything, but it greatly improves
readability of the XML.
BTW, in practice, I never use the generated @type attribute, so you may
want to leave it out.
Below is part of my code.
Pieter
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
\xA0\xA0\xA0 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
\xA0\xA0\xA0 xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:sanoma="http://www.sanoma-learning.com/namespaces/scripting/1"
\xA0\xA0\xA0 version="3.0">
\xA0\xA0\xA0 <!-- Stuff left out -->
\xA0\xA0\xA0 <xsl:function name="sanoma:is-ncname" as="xs:boolean">
\xA0\xA0\xA0\xA0\xA0\xA0\xA0 <xsl:param name="str" as="xs:string"/>
\xA0\xA0\xA0\xA0\xA0\xA0\xA0 <xsl:sequence select="$str castable as xs:NCName"></xsl:sequence>
\xA0\xA0\xA0 </xsl:function>
\xA0\xA0\xA0 <!-- Replace any json-construct like <string key="">, <map key="">
etc. with an XML element named after the value of key, if the value of
key allows it.
\xA0\xA0\xA0\xA0\xA0\xA0\xA0\xA0 This makes the XML coming from JSON, and hence XPath
expressions, much more readable and simple.
\xA0\xA0\xA0 -->
\xA0\xA0\xA0 <xsl:template match="*[@key and sanoma:is-ncname(@key)]">
\xA0\xA0\xA0\xA0\xA0\xA0\xA0 <xsl:element name="{@key}">
\xA0\xA0\xA0\xA0\xA0\xA0\xA0\xA0\xA0\xA0\xA0 <xsl:attribute name="type" select="name(.)"/>
\xA0\xA0\xA0\xA0\xA0\xA0\xA0\xA0\xA0\xA0\xA0 <xsl:apply-templates select="@* except @key | node()"/>
\xA0\xA0\xA0\xA0\xA0\xA0\xA0 </xsl:element>
\xA0\xA0\xA0 </xsl:template>
\xA0\xA0\xA0 <!-- Replace any json-construct without a key attribute with an XML
element named after the value of key of the parent, if there is a key
and if that key allows it.
\xA0\xA0\xA0\xA0\xA0\xA0\xA0\xA0 This will remove many elements with semantically empty names
like <map> and <array>. The XPath constructs that mention these elements
will be more easily understood.
\xA0\xA0\xA0 -->
\xA0\xA0\xA0 <xsl:template match="*[not(@key)]">
\xA0\xA0\xA0\xA0\xA0\xA0\xA0 <xsl:variable name="composed-name" as="xs:string" select="if
(parent::*[@key and sanoma:is-ncname(@key)]) then name(.) || '.' ||
parent::*/@key else name(.)"/>
\xA0\xA0\xA0\xA0\xA0\xA0\xA0 <xsl:element name="{$composed-name}">
\xA0\xA0\xA0\xA0\xA0\xA0\xA0\xA0\xA0\xA0\xA0 <xsl:attribute name="type" select="name(.)"/>
\xA0\xA0\xA0\xA0\xA0\xA0\xA0\xA0\xA0\xA0\xA0 <xsl:apply-templates select="@* | node()"/>
\xA0\xA0\xA0\xA0\xA0\xA0\xA0 </xsl:element>
\xA0\xA0\xA0 </xsl:template>
</xsl:stylesheet>
On 3/28/25 17:39, David Carlisle d.p.carlisle@xxxxxxxxx wrote:
>
>
> On Fri, 28 Mar 2025 at 16:30, dvint@xxxxxxxxx
> <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote:
>
> I'm processing content produced with json-to-xml(). So there are a
> buch
> of <map> elements. Many have the @key attribute and are easy to
> match.
> I'm drawing a blank on how to find map elements without the @key.
>
> <map key="mime">
> \xA0 \xA0 <string key="type">array</string>
> \xA0 \xA0 <array key="items">
> \xA0 \xA0 \xA0 \xA0<map>
> \xA0 \xA0 \xA0 \xA0 \xA0 <string key="type">string</string>
> \xA0 \xA0 \xA0 \xA0</map>
> \xA0 \xA0 </array
> \xA0 \xA0 </map>
> <map key="uri">
> \xA0 \xA0 <string key="type">string</string>
> </map>
> <map key="doctype">
> \xA0 \xA0 <string key="type">string</string>
> </map>
>
>
> Any thoughts? I tried map[@key=''] with no luck.
>
>
> map[not(@key)]
>
>
> ..dan
>
>
> XSL-List info and archive <http://www.mulberrytech.com/xsl/xsl-list>
> EasyUnsubscribe <http://lists.mulberrytech.com/unsub/xsl-list/3208261>
> (by email <>)
|