У меня есть следующий XML:
<?xml version="1.0" encoding="utf-8" ?>
<DOCUMENT>
<SECTION>
<PARAGRAPH TRACK="4">
<SENTENCE NAME="PRIMARY" COUNT="4">
<TOKEN BEGIN="9" END="11" SENTENCE_BEGIN="0" SENTENCE_END="156" />
<TOKEN BEGIN="32" END="37" SENTENCE_BEGIN="0" SENTENCE_END="156" />
<TOKEN BEGIN="167" END="169" SENTENCE_BEGIN="158" SENTENCE_END="316" />
<TOKEN BEGIN="210" END="215" SENTENCE_BEGIN="158" SENTENCE_END="316" />
</SENTENCE>
<SENTENCE NAME="SECONDARY" COUNT="2">
<TOKEN BEGIN="139" END="141" SENTENCE_BEGIN="0" SENTENCE_END="156" PROP="A" DOUBLE="YES" />
<TOKEN BEGIN="143" END="145" SENTENCE_BEGIN="0" SENTENCE_END="156" PROP="B" />
</SENTENCE>
<SENTENCE NAME="SECONDARY" COUNT="1">
<TOKEN BEGIN="17" END="19" SENTENCE_BEGIN="0" SENTENCE_END="156" PROP="C" DOUBLE="YES" />
</SENTENCE>
</PARAGRAPH>
</SECTION>
</DOCUMENT>
И мне нужно получить следующий результат с узлом TOKEN
, выбранным оператором IF
, обновленным атрибутом NEW
:
<?xml version="1.0" encoding="utf-8" ?>
<DOCUMENT>
<SECTION>
<PARAGRAPH TRACK="4">
<SENTENCE NAME="PRIMARY" COUNT="4">
<TOKEN BEGIN="9" END="11" SENTENCE_BEGIN="0" SENTENCE_END="156" />
<TOKEN BEGIN="32" END="37" SENTENCE_BEGIN="0" SENTENCE_END="156" />
<TOKEN BEGIN="167" END="169" SENTENCE_BEGIN="158" SENTENCE_END="316" />
<TOKEN BEGIN="210" END="215" SENTENCE_BEGIN="158" SENTENCE_END="316" />
</SENTENCE>
<SENTENCE NAME="SECONDARY" COUNT="2">
<TOKEN BEGIN="139" END="141" SENTENCE_BEGIN="0" SENTENCE_END="156" PROP="A" DOUBLE="YES" />
<TOKEN BEGIN="143" END="145" SENTENCE_BEGIN="0" SENTENCE_END="156" PROP="B" />
</SENTENCE>
<SENTENCE NAME="SECONDARY" COUNT="1">
<TOKEN BEGIN="17" END="19" SENTENCE_BEGIN="0" SENTENCE_END="156" PROP="C" DOUBLE="YES" NEW="YES" />
<TOKEN></TOKEN>
</SENTENCE>
</PARAGRAPH>
</SECTION>
</DOCUMENT>
Используя следующее преобразование XSLT, я получаю неверный результат, когда узел TOKEN
, выбранный оператором IF, копируется в начало дерева:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:key name="primary_tokens"
match="SENTENCE[@NAME='PRIMARY']/TOKEN"
use="concat(@SENTENCE_BEGIN,'|',@SENTENCE_END)"/>
<xsl:template match="/*">
<xsl:for-each select=".//TOKEN[@DOUBLE='YES'][key('primary_tokens',concat(@SENTENCE_BEGIN,'|',@SENTENCE_END))]">
<xsl:if test="key('primary_tokens',concat(@SENTENCE_BEGIN,'|',@SENTENCE_END))[@BEGIN > current()/@BEGIN]">
<xsl:copy>
<xsl:attribute name="NEW">YES</xsl:attribute>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:if>
</xsl:for-each>
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Нежелательный результат:
<?xml version="1.0" encoding="utf-16"?>
<TOKEN NEW="YES" BEGIN="17" END="19" SENTENCE_BEGIN="0" SENTENCE_END="156" PROP="C" DOUBLE="YES" />
<DOCUMENT>
<SECTION>
<PARAGRAPH TRACK="4">
<SENTENCE NAME="PRIMARY" COUNT="4">
<TOKEN BEGIN="9" END="11" SENTENCE_BEGIN="0" SENTENCE_END="156" />
<TOKEN BEGIN="32" END="37" SENTENCE_BEGIN="0" SENTENCE_END="156" />
<TOKEN BEGIN="167" END="169" SENTENCE_BEGIN="158" SENTENCE_END="316" />
<TOKEN BEGIN="210" END="215" SENTENCE_BEGIN="158" SENTENCE_END="316" />
</SENTENCE>
<SENTENCE NAME="SECONDARY" COUNT="2">
<TOKEN BEGIN="139" END="141" SENTENCE_BEGIN="0" SENTENCE_END="156" PROP="A" DOUBLE="YES" />
<TOKEN BEGIN="143" END="145" SENTENCE_BEGIN="0" SENTENCE_END="156" PROP="B" />
</SENTENCE>
<SENTENCE NAME="SECONDARY" COUNT="1">
<TOKEN BEGIN="17" END="19" SENTENCE_BEGIN="0" SENTENCE_END="156" PROP="C" DOUBLE="YES" />
</SENTENCE>
</PARAGRAPH>
</SECTION>
</DOCUMENT>
Я предложил возможное решение, добавив в xsl:template
условие match="//SECTION/PARAGRAPH/SENTENCE[@NAME='SECONDARY']/TOKEN
.К сожалению, даже это решение не является правильным, поскольку узел содержимого TOKEN
просто копируется в узел SENTENCE
:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:key name="primary_tokens"
match="SENTENCE[@NAME='PRIMARY']/TOKEN"
use="concat(@SENTENCE_BEGIN,'|',@SENTENCE_END)"/>
<xsl:template match="//SECTION/PARAGRAPH/SENTENCE[@NAME='SECONDARY']/TOKEN">
<xsl:for-each select="current()[key('primary_tokens',concat(@SENTENCE_BEGIN,'|',@SENTENCE_END))]">
<xsl:if test="key('primary_tokens',concat(@SENTENCE_BEGIN,'|',@SENTENCE_END))[@BEGIN > current()/@BEGIN]">
<xsl:attribute name="NEW">YES</xsl:attribute>
<xsl:apply-templates select="@*|node()"/>
</xsl:if>
</xsl:for-each>
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
Неправильный вывод с TOKEN
в узле SENTENCE
:
<?xml version="1.0" encoding="utf-16"?>
<DOCUMENT>
<SECTION>
<PARAGRAPH TRACK="4">
<SENTENCE NAME="PRIMARY" COUNT="4">
<TOKEN BEGIN="9" END="11" SENTENCE_BEGIN="0" SENTENCE_END="156" />
<TOKEN BEGIN="32" END="37" SENTENCE_BEGIN="0" SENTENCE_END="156" />
<TOKEN BEGIN="167" END="169" SENTENCE_BEGIN="158" SENTENCE_END="316" />
<TOKEN BEGIN="210" END="215" SENTENCE_BEGIN="158" SENTENCE_END="316" />
</SENTENCE>
<SENTENCE NAME="SECONDARY" COUNT="2">
<TOKEN BEGIN="139" END="141" SENTENCE_BEGIN="0" SENTENCE_END="156" PROP="A" DOUBLE="YES" />
<TOKEN BEGIN="143" END="145" SENTENCE_BEGIN="0" SENTENCE_END="156" PROP="B" />
</SENTENCE>
<SENTENCE NAME="SECONDARY" COUNT="1" NEW="YES" BEGIN="17" END="19" SENTENCE_BEGIN="0" SENTENCE_END="156" PROP="C" DOUBLE="YES">
<TOKEN BEGIN="17" END="19" SENTENCE_BEGIN="0" SENTENCE_END="156" PROP="C" DOUBLE="YES" />
<TOKEN />
</SENTENCE>
</PARAGRAPH>
</SECTION>
</DOCUMENT>
Мой вопрос: как получить желаемый результат, о котором говорилось выше?Моя вторая попытка близка к хорошему решению?