Bearbeiten als XML: Umgang mit langen Texten und &<">'

Description

Der Aufruf von "Bearbeiten als XML" scheitert bei Dokumenten mit langen Texten (bei mir >865 Zeichen) mit Stack-Overflow.
Das anschließende Speichern scheitert, wenn eines der Zeichen &<">' in einem Text enthalten ist.
Das ist beides in der Demoanwendung verifiziert.

Beteiligte Dateien:
mods2editor-viatxt.xsl
editor2mods-viatxt.xsl

Folgende Korrekturen haben bei mir gewirkt:

mods2editor-viatxt.xsl
{{
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:mods="http://www.loc.gov/mods/v3"
xmlns:mcrmods="xalan://org.mycore.mods.classification.MCRMODSClassificationSupport" exclude-result-prefixes="mcrmods" version="1.0">

<!-- rho 2016-10-07 Template escape-xml_100 wurde dazwischen geschaltet,
weil es einen Stack-overflow gab bei Element-Texten über 865 Zeichen. -->

<!-- 2016-11-10 rho: Korrektur des Umganges mit & < > ' und "
siehe auch editor2mods-viatxt.xml -->

<xsl:output
method="xml"
encoding="UTF-8" />

<xsl:template match="/">
<mycoreobject>
<!-- <xsl:text>&lt;comment&gt; rho 2016-10-07 einfach&lt;/comment&gt; </xsl:text> -->
<xsl:apply-templates />
</mycoreobject>
</xsl:template>

<xsl:template match="*">
<xsl:text>&lt;</xsl:text>
<xsl:value-of select="name()"/>
<xsl:if test="name()='mods'">
<xsl:text> xmlns="http://www.loc.gov/mods/v3"</xsl:text>
</xsl:if>
<xsl:for-each select="@*">
<xsl:value-of select="' '" />
<xsl:value-of select="name()" />
<xsl:value-of select="'='" />
<xsl:text>"</xsl:text>
<xsl:value-of select="." />
<xsl:text>"</xsl:text>
</xsl:for-each>
<xsl:text>&gt;</xsl:text>
<xsl:apply-templates/>
<xsl:text>&lt;/</xsl:text>
<xsl:value-of select="name()"/>
<xsl:text>&gt;</xsl:text>
</xsl:template>

<xsl:template match="text()">
<xsl:call-template name="escape-xml_100"><!-- rho 2016-10-07 -->
<xsl:with-param name="text" select="."/>
</xsl:call-template>
</xsl:template>

<!-- rho 2016-10-07 dieses Template wurde dazwischen geschaltet, weil es einen Stack-overflow gab bei Element-Texten über 865 Zeichen. -->
<xsl:template name="escape-xml_100">
<xslaram name="text" />
<xsl:if test="$text != ''">
<xsl:variable name="head" select="substring($text, 1, 100)" />
<xsl:variable name="tail" select="substring($text, 101)" />

<xsl:call-template name="escape-xml">
<xsl:with-param name="text" select="$head" />
</xsl:call-template>

<xsl:call-template name="escape-xml_100">
<xsl:with-param name="text" select="$tail" />
</xsl:call-template>
</xsl:if>
</xsl:template>

<xsl:template name="escape-xml">
<xslaram name="text" />
<xsl:if test="$text != ''">
<xsl:variable name="head" select="substring($text, 1, 1)" />
<xsl:variable name="tail" select="substring($text, 2)" />
<xsl:choose>
<!-- 2016-11-10 rho: Korrektur des Umganges mit & < > ' und "
die mehrfachangeber von 'amp;' wurde entfernt. -->

<xsl:when test="$head = '&amp;'">&amp;amp;</xsl:when>
<xsl:when test="$head = '&lt;'">&amp;lt;</xsl:when>
<xsl:when test="$head = '&gt;'">&amp;gt;</xsl:when>
<xsl:when test="$head = '&quot;'">&amp;quot;</xsl:when>
<xsl:when test="$head = &quot;&apos;&quot;">&amp;apos;</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$head" />
</xsl:otherwise>
</xsl:choose>
<xsl:call-template name="escape-xml">
<xsl:with-param name="text" select="$tail" />
</xsl:call-template>
</xsl:if>
</xsl:template>

</xsl:stylesheet>
}}

editor2mods-viatxt.xsl

{{<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:mcr="http://www.mycore.org/" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xalan="http://xml.apache.org/xalan" xmlns:mods="http://www.loc.gov/mods/v3" xmlns:mcrmods="xalan://org.mycore.mods.classification.MCRMODSClassificationSupport"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:gnd="http://d-nb.info/gnd/" xmlns:java="http://xml.apache.org/xalan/java"
xmlns:char="character" exclude-result-prefixes="gnd rdf mcrmods mcr xalan java" version="1.0">

<char:char ent="lt">&lt;</char:char>
<char:char ent="gt">&gt;</char:char>
<char:char ent="amp">&amp;</char:char>
<char:char ent="apos">&apos;</char:char>
<char:char ent="quot">&quot;</char:char>

<!-- 2016-11-10 rho: Korrektur des Umganges mit & < > ' und "
siehe auch mods2editor-viatxt.xml -->
<xsl:output
method="xml"
version="1.0"
indent="yes"
encoding="UTF-8" />

<xsl:template match="/">
<xsl:call-template name="parse">
<xsl:with-param name="str" select="."/>
</xsl:call-template>
</xsl:template>

<xsl:template name="parse">
<xslaram name="str" select="." />

<xsl:choose>
<xsl:when test="$str=''"></xsl:when> <!-- 2016-11-10 rho normalize-text nicht aufrufen -->

<xsl:when test="contains($str,'&lt;')">
<xsl:variable name="tag"
select="substring-before(substring-after($str,'&lt;'),'&gt;')" />
<xsl:variable name="endTag">
<xsl:choose>
<xsl:when test="contains($tag,' ')">
<xsl:value-of select="substring-before($tag,' ')" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$tag" />
</xsl:otherwise>
</xsl:choose>
</xsl:variable>

<xsl:call-template name="parse">
<xsl:with-param name="str"
select="substring-before($str,concat('&lt;',$tag,'&gt;'))" />
</xsl:call-template>

<xsl:call-template name="parseTag">
<xsl:with-param name="tag" select="$tag" />
<xsl:with-param name="endTag" select="normalize-space($endTag)" />
<xsl:with-param name="value"
select="substring-before(substring-after($str,concat('&lt;',$tag,'&gt;')),concat('&lt;/',normalize-space($endTag),'&gt;'))" />
</xsl:call-template>
<xsl:choose>
<xsl:when test="substring($tag,string-length($tag))='/'">
<xsl:call-template name="parse">
<xsl:with-param name="str"
select="substring-after($str,concat('&lt;',$tag,'&gt;'))" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="parse">
<xsl:with-param name="str"
select="substring-after($str,concat('&lt;/',normalize-space($endTag),'&gt;'))" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<!-- xsl:value-of select="$str" / -->
<xsl:call-template name="normalize-text">
<xsl:with-param name="text" select="$str" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>

<xsl:template name="parseTag">
<xslaram name="tag" select="''" />
<xslaram name="endTag" select="''" />
<xslaram name="value" select="''" />
<xsl:element name="{translate($endTag,'/','')}">
<xsl:call-template name="attribs">
<xsl:with-param name="attrlist"
select="substring-after(normalize-space($tag),' ')" />
</xsl:call-template>
<xsl:call-template name="parse">
<xsl:with-param name="str" select="$value" />
</xsl:call-template>
</xsl:element>
</xsl:template>

<xsl:template name="attribs">
<xslaram name="attrlist" select="''" />
<xsl:variable name="name"
select="normalize-space(substring-before($attrlist,'='))" />
<xsl:if test="$name">
<xsl:variable name="value">
<xsl:choose>
<xsl:when test="substring-before($attrlist,'=&quot;')">
<xsl:value-of
select="substring-before(substring-after($attrlist,'=&quot;'),'&quot;')" />
</xsl:when>
<xsl:when test="substring-before($attrlist,'= &quot;')">
<xsl:value-of
select="substring-before(substring-after($attrlist,'= &quot;'),'&quot;')" />
</xsl:when>
<xsl:when test="substring-before($attrlist,&quot;=&apos;&quot">
<xsl:value-of
select="substring-before(substring-after($attrlist,&quot;=&apos;&quot,&quot;&apos;&quot" />
</xsl:when>
<xsl:when test="substring-before($attrlist,&quot;= &apos;&quot">
<xsl:value-of
select="substring-before(substring-after($attrlist,&quot;=&apos;&quot,&quot;&apos;&quot" />
</xsl:when>
</xsl:choose>
</xsl:variable>
<xsl:attribute name="{$name}">
<xsl:value-of select="$value" />
</xsl:attribute>
</xsl:if>
<xsl:choose>
<xsl:when test="contains($attrlist,' ')">
<xsl:call-template name="attribs">
<xsl:with-param name="attrlist"
select="substring-after($attrlist,' ')" />
</xsl:call-template>
</xsl:when>
</xsl:choose>
</xsl:template>

<xsl:template name="normalize-text">
<xslaram name="text" />
<xsl:choose>
<xsl:when test="contains($text,'&amp;')">
<xsl:variable name="vAfter" select="substring-after($text,'&amp;')" /> <!-- 2016-11-10 rho: den Text vorher ausgeben-->
<xsl:value-of select="substring-before($text,'&amp;')"/>

<xsl:value-of select="concat('&amp;',substring-before($vAfter,';'),';')"
disable-output-escaping="yes"/> <!-- 2016-11-10 rho: &...; mit disable-output-escaping -->

<xsl:call-template name="normalize-text"> <!-- 2016-11-10 rho: den Text dahinter untersuchen -->
<xsl:with-param name="text" select="substring-after($vAfter,';')" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>}}

Environment

None

Assignee

Kathleen Neumann

Reporter

Ralph Hollenbach

Labels

URL

None

External issue ID

None

Components

Fix versions

Affects versions

Priority

Medium
Configure