Не удается получить необходимые элементы XML с помощью XSLT2.0?
Это мой документ XML. Я хочу преобразовать этот XML-документ в другой XML-документ (см. Раздел "Требуемый выходной XML").
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
xmlns:v="urn:schemas-microsoft-com:vml">
<w:body>
<w:p>
<w:pPr>
</w:pPr>
<w:r>
<w:t>Text1-</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="Heading2" />
</w:pPr>
<w:r>
<w:t>Text2-</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
</w:pPr>
<w:r>
<w:t>Text3-</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
</w:pPr>
<w:r>
<w:t>Text4-</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="Heading3" />
</w:pPr>
<w:r>
<w:t>Text2.1-</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="Heading2" />
</w:pPr>
<w:r>
<w:t>Text5-</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
</w:pPr>
<w:r>
<w:t>Text6-</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="Heading3" />
</w:pPr>
<w:r>
<w:t>Text7-</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
</w:pPr>
<w:r>
<w:t>Text8-</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="Heading1" />
</w:pPr>
<w:r>
<w:t>Text9-</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
</w:pPr>
<w:r>
<w:t>Text10-</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="Heading2" />
</w:pPr>
<w:r>
<w:t>Text11-</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
</w:pPr>
<w:r>
<w:t>Text12-</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:pict>
<v:shape>
<v:textbox>
<w:txbxcontent>
<w:p>
<w:pPr>
<w:pStyle w:val="Heading1" />
</w:pPr>
<w:r>
<w:t>
Drawing Description_1
</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="Heading1" />
</w:pPr>
<w:r>
<w:t>
Drawing Description_2
</w:t>
</w:r>
</w:p>
</w:txbxcontent>
</v:textbox>
</v:shape>
</w:pict>
</w:r>
</w:p>
</w:body>
</w:document>
Требуемый выходной XML:
<?xml version="1.0" encoding="utf-8"?><Document xmlns:v="urn:schemas-microsoft-com:vml" xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture">
<Paragraph>Text1-</Paragraph>
<Heading2>
<Title>Text2-</Title>
<Paragraph>Text3-</Paragraph>
<Paragraph>Text4-</Paragraph>
<Heading3>
<Title>Text2.1-</Title>
</Heading3>
</Heading2>
<Heading2>
<Title>Text5-</Title>
<Paragraph>Text6-</Paragraph>
<Heading3>
<Title>Text7-</Title>
<Paragraph>Text8-</Paragraph>
</Heading3>
</Heading2>
<Heading1>
<Title>Text9-</Title>
<Paragraph>Text10-</Paragraph>
<Heading2>
<Title>Text11-</Title>
<Paragraph>Text12-</Paragraph>
<txtContentGroup>
<Paragraph>Drawing Description_1</Paragraph>
<Paragraph>Drawing Description_2</Paragraph>
</txtContentGroup>
</Heading2>
</Heading1>
</Document>
Это моя реализация XSLT 2.0 для этого:
<xsl:stylesheet
version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xpath-default-namespace="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
xmlns:mf="http://example.com/mf"
xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture"
xmlns:user="http://http://stackru.com/questions/11356668"
exclude-result-prefixes="xs w fn mf user">
<xsl:output indent="yes"/>
<xsl:function name="mf:group" as="element()*">
<xsl:param name="paragraphs" as="element()*"/>
<xsl:param name="level" as="xs:integer"/>
<xsl:for-each-group select="$paragraphs" group-starting-with="p[pPr/pStyle/@w:val = concat('Heading', $level)]">
<xsl:choose>
<xsl:when test="self::p[pPr/pStyle/@w:val = concat('Heading', $level)]">
<xsl:element name="Heading{$level}">
<Title>
<xsl:apply-templates select="./r/t"/>
</Title>
<xsl:sequence select="mf:group(current-group() except ., $level + 1)"/>
</xsl:element>
</xsl:when>
<xsl:when test="current-group()[self::p[pPr/pStyle/@w:val = concat('Heading', $level + 1)]]">
<xsl:sequence select="mf:group(current-group(), $level + 1)">
</xsl:sequence>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()">
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:function>
<xsl:template match="document">
<Document>
<xsl:sequence select="mf:group(body/p, 1)"/>
</Document>
</xsl:template>
<xsl:template match="p">
<xsl:choose>
<xsl:when test="(./r/t)">
<xsl:choose>
<xsl:when test="descendant::w:p[w:r/w:t] | descendant::w:p[//w:r/w:t[ancestor::w:pict]][2] ">
<txtContentGroup>
<Paragraph>
<xsl:apply-templates select="./r/t"/>
</Paragraph>
<xsl:apply-templates select="descendant::w:p">
</xsl:apply-templates>
</txtContentGroup>
</xsl:when>
<xsl:otherwise>
<Paragraph>
<xsl:apply-templates select="./r/t"/>
</Paragraph>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test="descendant::w:p[not(ancestor::w:tbl)]">
<xsl:apply-templates select="descendant::w:p">
</xsl:apply-templates>
</xsl:when>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="/r/t">
<xsl:value-of select="."/>
</xsl:template>
</xsl:stylesheet>
Но он генерирует следующий вывод:
<?xml version="1.0" encoding="utf-8"?><Document xmlns:v="urn:schemas-microsoft-com:vml" xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture">
<Paragraph>Text1-</Paragraph>
<Heading2>
<Title>Text2-</Title>
<Paragraph>Text3-</Paragraph>
<Paragraph>Text4-</Paragraph>
<Heading3>
<Title>Text2.1-</Title>
</Heading3>
</Heading2>
<Heading2>
<Title>Text5-</Title>
<Paragraph>Text6-</Paragraph>
<Heading3>
<Title>Text7-</Title>
<Paragraph>Text8-</Paragraph>
</Heading3>
</Heading2>
<Heading1>
<Title>Text9-</Title>
<Paragraph>Text10-</Paragraph>
<Heading2>
<Title>Text11-</Title>
<Paragraph>Text12-</Paragraph>
<Paragraph>Drawing Description_1</Paragraph>
<Paragraph>Drawing Description_2</Paragraph>
</Heading2>
</Heading1>
</Document>
Мое состояние:
Всякий раз, когда <w:p>
элементы содержат более одного descendant::w:p[w:r/w:t]
в этом, а также что descendant::w:p[w:r/w:t]
имеет предка <w:pict>
тогда я хочу создать <txtContentGroup>
элементы и положить все descendant::w:p[w:r/w:t]
внутри него.
Пожалуйста, помогите мне выйти из этой проблемы...
1 ответ
При таком типе ввода вы должны использовать шаблонные правила, а не глубоко вложенные xsl: выбирать инструкции. Ваше английское высказывание
Всякий раз, когда <w:p>
элементы содержат более одного descendant::w:p[w:r/w:t]
в нем, а также у него есть предок <w:pict>
тогда я хочу создать <txtContentGroup>
элементы и положить все descendant::w:p[w:r/w:t]
внутри него.
сопоставляется непосредственно с правилом шаблона:
<xsl:template match="w:pict//w:p[descendant::w:p[w:r/w:t][2]]">
<textContentGroup>
<xsl:apply-templates select="descendant::w:p[w:r/w:t]"/>
</textContentGroup>
</xsl:template>