XSL изменяет контекстный узел внутри цикла foreach - PullRequest
0 голосов
/ 02 марта 2020

У меня есть следующее xml:

<project>
  <workitem id="x1640" linecount="2">
    <texts>
      <text language="en" >English text in one line</text>
      <text language="fr" >German text in <newline/>two lines</text>
      <text language="de" >French text in <newline/>two lines</text>
    </texts>
  </workitem>
  <workitem id="x1640" linecount="2">
  </workitem>
</project>

Мне нужно преобразовать его в следующее. Для каждой строки в text мне нужно создать новый элемент textitem, например:

<root>
  <textitem id="x1640-1">
    <en>English text in one line</text>
    <fr>German text in</fr>
    <de>French text in</de>
  </textitem>
  <textitem id="x1640-2">
    <en></en>
    <fr>two lines</fr>
    <de>two lines</de>
  </textitem>
</root>

Так что моя идея заключалась в том, чтобы перебрать linecount таким образом в фальшивом для-l oop, но с этим я теряю узел контекста. Есть ли шанс вернуть контекст внутри foreach обратно на workitem? Или мне нужен совершенно другой подход? Любые предложения будут отличными, спасибо!

<xsl:stylesheet version="2" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
    <root>
        <xsl:apply-templates select="project/workitem" />
    </root>
</xsl:template>

<xsl:template match="workitem">
    <xsl:variable name="lines" select="1"/>
        <!--
    <xsl:for-each select="1 to ./@linecount">   
        -->
        <textitem>
            <xsl:attribute name="id"><xsl:value-of select="concat(@id,'-',$lines)" /></xsl:attribute>
            <xsl:apply-templates select="texts/text" >
                <xsl:with-param name="linecount" select="$lines" />
            </xsl:apply-templates>
        </textitem>
        <!--
    </xsl:for-each>
        -->
</xsl:template>

<xsl:template match="text">
    <xsl:param name="linecount"/>
    <xsl:variable name="lang" select="@language" />
    <xsl:element name="{$lang}">
        <xsl:value-of select="./text()[count(preceding-sibling::newline)=($linecount - 1)]" />
        <xsl:apply-templates />
    </xsl:element>
</xsl:template>

<xsl:template match="text()">
</xsl:template>

1 Ответ

2 голосов
/ 02 марта 2020

Если вы объявите <xsl:variable name="workitem" select="."/> перед for-each, у вас наверняка будет доступ к переменной $workitem внутри for-each. Затем я бы предложил использовать или передать элемент контекста for-each, то есть номер строки, и использовать text()[$line-nr] для выбора соответствующих текстовых узлов.

...