Вот решение, что, в отличие от в настоящее время общепринятый ответ, обрабатывает правильно данные с различными, заранее неизвестно, длина - см дополнительно обновление, которое обрабатывает неограниченное число столбцов, слишком:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:variable name="vMax1">
<xsl:call-template name="maxLength">
<xsl:with-param name="pNodes" select="/*/*/*[1]"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="vMax2">
<xsl:call-template name="maxLength">
<xsl:with-param name="pNodes" select="/*/*/*[2]"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="vLongest1" select=
"/*/*/*[1][string-length() = $vMax1][1]"/>
<xsl:variable name="vLongest2" select=
"/*/*/*[2][string-length() = $vMax2][1]"/>
<xsl:variable name="vUnderscores1" select=
"concat('__',
translate($vLongest1,translate($vLongest1, '_', ''),
'_________________________________________________________')
)"/>
<xsl:variable name="vUnderscores2" select=
"concat('__',
translate($vLongest2,translate($vLongest2, '_', ''),
'_________________________________________________________')
)"/>
<xsl:variable name="vBlanks1"
select="translate($vUnderscores1,'_', ' ')"/>
<xsl:variable name="vBlanks2"
select="translate($vUnderscores2,'_', ' ')"/>
<xsl:variable name="vTitle1" select=
"concat('[',/*/*/*[1],']',
substring($vBlanks1,1,
string-length($vBlanks1)-string-length(/*/*/*[1]))
)"/>
<xsl:variable name="vTitle2" select=
"concat('[',/*/*/*[2],']',
substring($vBlanks2,1,
string-length($vBlanks2)-string-length(/*/*/*[2]))
)"/>
<xsl:template match="Row">
<xsl:value-of select=
"concat('
', $vTitle1, $vTitle2)"/>
<xsl:value-of select=
"concat('
',$vUnderscores1, ' ', $vUnderscores2, '
')"/>
<xsl:value-of select=
"concat(F1,
substring($vBlanks1,1,
string-length($vBlanks1)-string-length(F1)),
' ',
F2,
substring($vBlanks1,1,
string-length($vBlanks1)-string-length(F2)),
'
'
)"/>
</xsl:template>
<xsl:template name="maxLength">
<xsl:param name="pNodes" select="/.."/>
<xsl:for-each select="$pNodes">
<xsl:sort select="string-length()"
data-type="number" order="descending"/>
<xsl:if test="position() = 1">
<xsl:value-of select="string-length()"/>
</xsl:if>
</xsl:for-each>
</xsl:template>
<xsl:template match="Row[1]|text()"/>
</xsl:stylesheet>
Когда это преобразование применяются на предоставленном документе XML:
<Data>
<Row>
<F1>Created By</F1>
<F2>City</F2>
</Row>
<Row>
<F1>John Doe</F1>
<F2>Los Angeles</F2>
</Row>
<Row>
<F1>Jane Doe</F1>
<F2>San Diego</F2>
</Row>
</Data>
разыскиваемых, правильный результат получается:
[Created By] [City]
____________ _____________
John Doe Los Angeles
[Created By] [City]
____________ _____________
Jane Doe San Diego
Более интересно, при нанесении на этом XML-документа:
<Data>
<Row>
<F1>Created By</F1>
<F2>City</F2>
</Row>
<Row>
<F1>John Doe</F1>
<F2>La Villa Real de la Santa Fe de San Francisco de Asis</F2>
</Row>
<Row>
<F1>Josiah Willard Gibbs</F1>
<F2>San Diego</F2>
</Row>
</Data>
снова правильные результаты получают:
[Created By] [City]
______________________ _______________________________________________________
John Doe La Villa Real de la Santa Fe de San Francisco de Asis
[Created By] [City]
______________________ _______________________________________________________
Josiah Willard Gibbs San Diego
Сравните этот корр. ЭСТ результат с тем, производимого в настоящее время общепринятый ответ:
Created By City
----------- -----------
John Doe La Villa Real de la Santa Fe de San Francisco de Asis
Created By City
----------- -----------
Josiah Willard GibbsSan Diego
II XSLT 2.0 вариант того же раствора: короче и легче писать:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output method="text"/>
<xsl:variable name="vMax" as="xs:integer*" select=
"for $i in 1 to 2
return
max(/*/*/*[$i]/string-length(.))"/>
<xsl:variable name="vUnderscores" select=
"for $i in 1 to 2
return
concat('__',
string-join((for $len in 1 to $vMax[$i]
return '_'), '')
)"/>
<xsl:variable name="vBlanks" select=
"for $i in 1 to 2
return
translate($vUnderscores[$i],'_', ' ')
"/>
<xsl:variable name="vTitle" select=
"for $i in 1 to 2
return
concat('[',(*/*/*)[$i],']',
substring($vBlanks[$i],1,
$vMax[$i]+2 -string-length((/*/*/*)[$i]))
)
"/>
<xsl:template match="Row">
<xsl:value-of select=
"concat('
', $vTitle[1], $vTitle[2])"/>
<xsl:value-of select=
"concat('
',$vUnderscores[1], ' ', $vUnderscores[2], '
')"/>
<xsl:value-of select=
"concat(F1,
substring($vBlanks[1],1,
$vMax[1]+2 -string-length(F1)),
' ',
F2,
substring($vBlanks[2],1,
$vMax[1]+2 -string-length(F2)),
'
'
)"/>
</xsl:template>
<xsl:template match="Row[1]|text()"/>
</xsl:stylesheet>
III. Обработка idefinite количество столбцов:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output method="text"/>
<xsl:variable name="vNumCols" select="max(/*/*/count(*))"/>
<xsl:variable name="vMax" as="xs:integer*" select=
"for $i in 1 to $vNumCols
return
max(/*/*/*[$i]/string-length(.))"/>
<xsl:variable name="vUnderscores" select=
"for $i in 1 to $vNumCols
return
concat('__',
string-join((for $len in 1 to $vMax[$i]
return '_'), '')
)"/>
<xsl:variable name="vBlanks" select=
"for $i in 1 to $vNumCols
return
translate($vUnderscores[$i],'_', ' ')
"/>
<xsl:variable name="vTitle" select=
"for $i in 1 to $vNumCols
return
concat('[',(*/*/*)[$i],']',
substring($vBlanks[$i],1,
$vMax[$i]+2 -string-length((/*/*/*)[$i]))
)
"/>
<xsl:template match="Row">
<xsl:value-of separator="" select=
"'
', string-join($vTitle, '')"/>
<xsl:value-of separator="" select=
"'
', string-join($vUnderscores, ' '), '
'"/>
<xsl:value-of select=
"string-join((for $i in 1 to $vNumCols,
$vChild in *[$i]
return
($vChild,
substring($vBlanks[$i],1,
$vMax[$i]+2 -string-length($vChild)
),
' '
),
'
'
),
''
)"/>
</xsl:template>
<xsl:template match="Row[1]|text()"/>
</xsl:stylesheet>
При применении этого XML-документа (3 колонки):
<Data>
<Row>
<F1>Created By</F1>
<F2>City</F2>
<F3>Region</F3>
</Row>
<Row>
<F1>Pablo Diego Ruiz y Picasso</F1>
<F2>Los Angeles</F2>
<F3>CA</F3>
</Row>
<Row>
<F1>Jane Doe</F1>
<F2>La Villa Real de la Santa Fe de San Francisco de Asis</F2>
<F3>NM</F3>
</Row>
</Data>
разыскиваемый, правильный результат получается:
[Created By] [City] [Region]
____________________________ _______________________________________________________ ________
Pablo Diego Ruiz y Picasso Los Angeles CA
[Created By] [City] [Region]
____________________________ _______________________________________________________ ________
Jane Doe La Villa Real de la Santa Fe de San Francisco de Asis NM
IV. Перевод в XSLT 1.0 Части III (выше):
Обратите внимание:
решение, которое JLRishe обеспеченное как исправление его первоначального ответа, будет выполнять своего рода 400 раз, если имеется 100 строк, каждая с 4 столбца.
Нет такой неэффективности в коде ниже:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ext="http://exslt.org/common">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:variable name="vMaxCols">
<xsl:call-template name="maxChildren">
<xsl:with-param name="pNodes" select="/*/*"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="vrtfMax">
<xsl:for-each select="(/*/*/*)[not(position() > $vMaxCols)]">
<xsl:variable name="vPos" select="position()"/>
<length>
<xsl:call-template name="maxLength">
<xsl:with-param name="pNodes" select="/*/*/*[position()=$vPos]"/>
</xsl:call-template>
</length>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="vMax" select="ext:node-set($vrtfMax)/length"/>
<xsl:variable name="vrtfUnderscores">
<xsl:for-each select="(/*/*/*)[not(position() > $vMaxCols)]">
<xsl:variable name="vPos" select="position()"/>
<xsl:variable name="vLongestDataNode" select=
"/*/*/*[position()=$vPos
and string-length() = $vMax[position() = $vPos]][1]"/>
<t>
<xsl:value-of select=
"concat('__',
translate($vLongestDataNode,translate($vLongestDataNode, '_', ''),
'_________________________________________________________')
)"/>
</t>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="vUnderscores" select="ext:node-set($vrtfUnderscores)/t"/>
<xsl:variable name="vrtfBlanks">
<xsl:for-each select="$vUnderscores">
<xsl:variable name="vPos" select="position()"/>
<t><xsl:value-of select=
"translate($vUnderscores[position()=$vPos],'_', ' ')"/>
</t>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="vBlanks" select="ext:node-set($vrtfBlanks)/t"/>
<xsl:variable name="vrtfTitle">
<xsl:for-each select="/*/*[1]/*">
<xsl:variable name="vPos" select="position()"/>
<t>
<xsl:value-of select=
"concat('[',.,']',
substring($vBlanks[position()=$vPos],1,
2+$vMax[position()=$vPos]-string-length())
)
"/>
</t>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="vTitle" select="ext:node-set($vrtfTitle)/t"/>
<xsl:template match="Row">
<xsl:text>
</xsl:text>
<xsl:for-each select="$vTitle">
<xsl:value-of select="."/>
</xsl:for-each>
<xsl:text>
</xsl:text>
<xsl:for-each select="$vUnderscores">
<xsl:value-of select="."/>
<xsl:text> </xsl:text>
</xsl:for-each>
<xsl:text>
</xsl:text>
<xsl:for-each select="*[not(position() > $vMaxCols)]">
<xsl:variable name="vPos" select="position()"/>
<xsl:value-of select=
"concat(.,
substring($vBlanks[position()=$vPos],
1,
string-length($vBlanks[position()=$vPos])
-string-length()),
' '
)"/>
</xsl:for-each>
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template name="maxChildren">
<xsl:param name="pNodes" select="/.."/>
<xsl:for-each select="$pNodes">
<xsl:sort select="count(*)"
data-type="number" order="descending"/>
<xsl:if test="position() = 1">
<xsl:value-of select="count(*)"/>
</xsl:if>
</xsl:for-each>
</xsl:template>
<xsl:template name="maxLength">
<xsl:param name="pNodes" select="/.."/>
<xsl:for-each select="$pNodes">
<xsl:sort select="string-length()"
data-type="number" order="descending"/>
<xsl:if test="position() = 1">
<xsl:value-of select="string-length()"/>
</xsl:if>
</xsl:for-each>
</xsl:template>
<xsl:template match="Row[1]|text()"/>
</xsl:stylesheet>
ли вы на самом деле хотите, открытый текст, как, что, как выход, или вы хотите, это как HTML? Если да, не могли бы вы показать нам, что вы хотите, чтобы HTML (сам код) выглядел? – JLRishe
Мне нравится простой текст. Я просто обновил вывод из моего вопроса. – user2177441
Хорошо, спасибо за разъяснение. Итак, вы хотите скобки вокруг имен столбцов или имена столбцов _and_ значения? – JLRishe