2016-03-29 1 views
0

Мне нравится извлекать номера глав, их название и их описание из XML-файла в иерархию элементов/атрибутов XML. Они распределены в непрерывном тексте в разных элементах. XML выглядит следующим образом:XSLT 2.0: создайте RegEx для перечисления номеров и описания разделов с непрерывными текстовыми узлами

<?xml version="1.0" encoding="utf-8"?> 
<root> 
    <cell>3.1.1.17 First Section The “First appropriate” section lists things that can occur when an event happens. All of these event conditions result in an error. 
    </cell> 
    <cell>3.1.1.18 Second Section This section lists things that occur under certain conditions. 3.1.1.19 Third Section This section lists events that occur within a specific space. 3.2 SPACE chapter provides descriptions other stuff. See also: Chapter 4, “Other Stuff Reference” in the Manual. 
    </cell> 
</root> 

желаемый результат должен выглядеть следующим образом:

<?xml version="1.0" encoding="utf-8"?> 
<Root> 
    <Desc chapter="3.1.1.17" title="First Section">The “First appropriate” section lists things that can occur when an event happens. All of these event conditions result in an error.</Desc> 
    <Desc chapter="3.1.1.18" title="Second Section">This section lists things that occur under certain conditions.</Desc> 
    <Desc chapter="3.1.1.19" title="Third Section">This section lists events that occur within a specific space. 3.2 SPACE chapter provides descriptions other stuff. See also: Chapter 4, “Other Stuff Reference” in the Manual.</Desc> 
</Root> 

Мой XSLT до сих пор:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output indent="yes" method="xml" encoding="utf-8" /> 

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

    <xsl:template match="/root"> 
    <Root> 
     <xsl:apply-templates select="cell" /> 
    </Root> 
    </xsl:template> 

    <xsl:template match="cell"> 
    <xsl:variable name="sections" as="element(Desc)*"> 
     <xsl:analyze-string regex="(\d+\.\d+\.\d+\.\d+)\s(.*?Section)(.*?)" select="text()"> 
     <xsl:matching-substring> 
      <Desc chapter="{regex-group(1)}" title="{regex-group(2)}"> 
      <xsl:value-of select="regex-group(3)" /> 
      </Desc> 
     </xsl:matching-substring> 
     </xsl:analyze-string> 
    </xsl:variable> 
    <xsl:for-each select="$sections"> 
     <xsl:copy-of select="." /> 
    </xsl:for-each> 
    </xsl:template> 
</xsl:stylesheet> 

проблема находится в последней части RegEx: (.*?) - неживое употребляющее выражение. К сожалению, я не могу заставить его остановиться в правильном положении. Я попытался использовать ?: и (?=...), чтобы остановить его до следующего \d+\.\d+\.\d+\.\d+\., но похоже, что синтаксис RegEx XSLT-2.0 несколько отличается от других диалектов.

Как извлечь соответствующие части для удобного их обработки в for-each как regex-group(1..3)?

И, кроме того, меня интересует довольно полная ссылка XSLT-2.0 всех токенов RegEx.

ответ

0

кажется

<xsl:template match="cell"> 
    <xsl:variable name="sections"> 
     <xsl:analyze-string regex="(\d+\.\d+\.\d+\.\d+)\s(.*?Section)" select="."> 
      <xsl:matching-substring> 
       <xsl:message select="concat('|', regex-group(3), '|')"/> 
       <Desc chapter="{regex-group(1)}" title="{regex-group(2)}"> 
        <xsl:value-of select="regex-group(3)" /> 
       </Desc> 
      </xsl:matching-substring> 
      <xsl:non-matching-substring> 
       <Value> 
        <xsl:value-of select="."/> 
       </Value> 
      </xsl:non-matching-substring> 
     </xsl:analyze-string> 
    </xsl:variable> 
    <xsl:for-each select="$sections/Desc"> 
     <xsl:copy> 
      <xsl:copy-of select="@*"/> 
      <xsl:value-of select="following-sibling::Value[1]"/> 
     </xsl:copy> 
    </xsl:for-each> 
</xsl:template> 

фиксирует как данные, которые вы хотите выбрать и текст косой.

+0

спасибо. Использование 'xsl: non-matching-substring' - отличная идея. – zx485

0

Извините, что я должен ответить в JS, но я верю, что вы можете просто выяснить, что происходит. Ваше регулярное выражение и его решение должно быть таким:

var xmlData = '<?xml version="1.0" encoding="utf-8"?>\n<root>\n <cell>3.1.1.17 First Section The “First appropriate” section lists things that can occur when an event happens. All of these event conditions result in an error.\n </cell>\n <cell>3.1.1.18 Second Section This section lists things that occur under certain conditions. 3.1.1.19 Third Section This section lists events that occur within a specific space. 3.2 SPACE chapter provides descriptions other stuff. See also: Chapter 4, “Other Stuff Reference” in the Manual.\n </cell>\n</root>', 
     rex = /<cell>(?:\s*(\d+.\d+.\d+.\d+)\s+(\w+)\s+Section)(.+)\n*\s*<\/cell>/gm, 
     xml = xmlData.replace(rex,'<Desc chapter="$1" title="$2 Section">$3</desc>'); 
console.log(xmlData); 
<?xml version="1.0" encoding="utf-8"?> 
<root> 
    <Desc chapter="3.1.1.17" title="First Section"> The “First appropriate” section lists things that can occur when an event happens. All of these event conditions result in an error.</desc> 
    <Desc chapter="3.1.1.18" title="Second Section"> This section lists things that occur under certain conditions. 3.1.1.19 Third Section This section lists events that occur within a specific space. 3.2 SPACE chapter provides descriptions other stuff. See also: Chapter 4, “Other Stuff Reference” in the Manual.</desc> 
</root>