извлечь cdata с помощью xslt - PullRequest
       0

извлечь cdata с помощью xslt

1 голос
/ 14 сентября 2010

Ниже приведен xml с разделом CDATA.

<?xml version="1.0" encoding="ISO-8859-1"?>
<character>
<name>
<role>Indiana Jones</role>
<actor>Harrison Ford</actor>
<part>protagonist</part>
<![CDATA[  <film>Indiana Jones and the Kingdom of the Crystal Skull</film>]]>
</name>
</character>

. Для вышеупомянутого xml мне нужно оторвать CDATA и добавить новый элемент в существующий элемент "film", поэтому окончательный результат будет:

<?xml version="1.0" encoding="ISO-8859-1"?>
<character>
<name>
<role>Indiana Jones</role>
<actor>Harrison Ford</actor>
<part>protagonist</part>
<film>Indiana Jones and the Kingdom of the Crystal Skull</film>
<Language>English</Language>
</name>
</character>

Можно ли это сделать с помощью XSLT?

Ответы [ 5 ]

3 голосов
/ 20 августа 2012

Должна работать слегка измененная функция идентификации.

Учитывая этот XML:

<?xml version="1.0" encoding="ISO-8859-1"?>
<character>
    <name>
        <role>Indiana Jones</role>
        <actor>Harrison Ford</actor>
        <part>protagonist</part>
        <![CDATA[  <film>Indiana Jones and the Kingdom of the Crystal Skull</film>]]>
    </name>
</character>

Использование этого XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">

    <xsl:output method="xml" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="*">
        <xsl:copy>
            <xsl:apply-templates select="*" />
            <xsl:value-of select="text()" disable-output-escaping="yes"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

Будет выдавать этот вывод:

<?xml version="1.0" encoding="UTF-8"?>
<character>
   <name>
      <role>Indiana Jones</role>
      <actor>Harrison Ford</actor>
      <part>protagonist</part>
          <film>Indiana Jones and the Kingdom of the Crystal Skull</film>
    </name>
</character>

(протестировано с использованием Saxon-HE 9.3.0.5 в oxygen 12.2.)

2 голосов
/ 14 сентября 2010

Поскольку элемент film в блоке CDATA выглядит правильно сформированным, вы можете использовать отключение-вывод-экранирование.Если вы соответствуете имени / тексту (), выберите значение-из с помощью DOE, а затем вставьте элемент Language сразу после.

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"  />

<!--Identity template simply copies content forward -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>


<xsl:template match="name/text()">
    <!--disable-output-escaping will prevent the "film" element from being escaped.
    Since it appears to be well-formed you should be safe, but no guarentees -->
    <xsl:value-of select="." disable-output-escaping="yes" />
    <Language>English</Language>
</xsl:template>

</xsl:stylesheet>
1 голос
/ 14 сентября 2010

Еще один способ решить эту проблему, который даст вам больше контроля над преобразованием, - использовать Andrew Welsh LexEv XMLReader . Это дает вам возможность обрабатывать разделы CDATA как разметку среди прочего.

0 голосов
/ 11 ноября 2013

Я имел дело с чем-то похожим и нашел хорошее решение, поэтому подумал поделиться им с вами, но это для NSXMLParser.

Если вы используете NSXMLParser, есть метод делегата foundCDATA, который может выглядеть следующим образом:

- (void)parser:(NSXMLParser *)parser foundCDATA:(NSData *)CDATABlock{
    if (!parseElement) {
        return;
    }
    if (parsedElementData==nil) {
        parsedElementData = [[NSMutableData alloc] init];
    }
    [parsedElementData appendData:CDATABlock];

    //Grabs the whole content in CDATABlock.
    NSMutableString *content = [[NSMutableString alloc] initWithData:CDATABlock encoding:NSUTF8StringEncoding];

 }

Теперь добавьте этот заранее написанный класс в ваш проект. Затем импортируйте его в класс анализатора, в котором вы хотите его использовать:

#import NSString_stripHTML

Теперь просто добавьте следующую строку в метод foundCDATA:

NSString *strippedContent;
strippedContent = [content strippedHtml];

Теперь у вас будет вырезанный текст без каких-либо дополнительных символов. Из этого вырезанного текста вы можете вставить все, что захотите.

0 голосов
/ 14 сентября 2010

Во-первых, тот факт, что ваш входной XML имеет "CDATA", в каком-то смысле не имеет значения ... XSLT не может определить, является ли он CDATA или нет. Что важно в вашем входном XML, так это то, что вы избежали разметки <film>...</film> и хотите превратить ее в настоящий элемент.

Если вы знаете, что у экранированного элемента всегда будет определенное имя («пленка»), и вы знаете, где оно происходит, вы можете удалить его и заменить его:

   <xsl:template match="text()[contains(., '&lt;film>')]">
      <film>
         <xsl:value-of select="substring-before(substring-after(., '&lt;film>'),
              '&lt;/film>')"/>
      </film>
   </xsl:template>

Если вы заранее не знаете, где появятся экранированные теги и как называются элементы, вы можете использовать XSLT 2.0 <xsl:analyze-string>, чтобы найти и заменить их. Но, как отметил Алехандро, общий синтаксический анализ XML с использованием регулярных выражений может быть очень запутанным. Это будет возможно, только если вы знаете, что разметка будет простой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...