Извлечь часть файла XML в виде обычного текста, используя XSLT - PullRequest
8 голосов
/ 18 июня 2011

Кажется, это должно быть легко, но ...

Я пытаюсь использовать XSLT для извлечения части XML-файла в виде простого текста, а остальные отбрасываю.

Так из примера ввода вот так ...

<?xml version="1.0" encoding="UTF-8"?>
<?oxygen RNGSchema="http://segonku.unl.edu/teianalytics/TEIAnalytics.rng"
                        type="xml"?>
<TEI xmlns="http://www.tei-c.org/ns/1.0" n="Wright2-0034.sgml.xml">
   <teiHeader type="text">
      <fileDesc>
         <titleStmt>
            <title>Header Title</title>
         </titleStmt>
         <publicationStmt>
            <p>Published</p>
         </publicationStmt>
         <sourceDesc>
            <p>Sourced</p>
         </sourceDesc>
      </fileDesc>
   </teiHeader>
   <text>
      <front>
      </front>
      <body>
         <head>THE TITLE</head>
         <div type="chapter" part="N" org="uniform" sample="complete">
            <head>CHAPTER I</head>
            <p>Some text.</p>
         </div>
      </body>
   </text>
</TEI>

... Я пытаюсь получить только текст, содержащийся в тегах <body> и всех их дочерних элементов. Желаемый результат в этом случае:

THE TITLE
CHAPTER I
Some text.

Потенциальное осложнение: <body> также может существовать в веществе <front> и / или в <teiHeader>, так что мне действительно нужны дети <body>, если и только если этот тег является потомком <text> и <TEI>.

Я пробовал действительно простой XSL, как этот ...

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="text"/>
    <xsl:template match="/TEI/text/body">
        <xsl:apply-templates select="."/>
    </xsl:template>
</xsl:stylesheet>

... но он дает мне простой текст всего файла, а не только элементов <body>.

Спасибо!

Ответы [ 3 ]

7 голосов
/ 18 июня 2011

Я пробовал действительно простой XSL, как этот ...

...

     <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 version="1.0">
         <xsl:output method="text"/>
         <xsl:template match="/TEI/text/body">
             <xsl:apply-templates select="."/>
         </xsl:template>
     </xsl:stylesheet>

... но он дает мне простой текст всего в файле, а не только <body> элементов.

Причиной этого является известное свойство / особенность XPath (и причина для многих тысяч подобных вопросов), позволяющая считать любое имя без префикса принадлежащим «без пространства имен».Однако любой элемент в предоставленном XML-документе принадлежит пространству имен: "http://www.tei -c.org / ns / 1.0" и должен быть доступен как узел в этом пространстве имен.

Решение : Определите пространство имен документов по умолчанию в коде XSLT (на этот раз с привязанным к нему префиксом) и используйте префикс при указании каждого имени.

Это одно из самых простых и кратчайших возможных преобразований, который дает желаемый результат:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:x="http://www.tei-c.org/ns/1.0">
 <xsl:output method="text"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="x:text/x:body//text()">
  <xsl:value-of select="concat(.,'&#xA;')"/>
 </xsl:template>
 <xsl:template match="text()"/>
</xsl:stylesheet>

При применении к предоставленному документу XML :

<TEI xmlns="http://www.tei-c.org/ns/1.0" n="Wright2-0034.sgml.xml">
    <teiHeader type="text">
        <fileDesc>
            <titleStmt>
                <title>Header Title</title>
            </titleStmt>
            <publicationStmt>
                <p>Published</p>
            </publicationStmt>
            <sourceDesc>
                <p>Sourced</p>
            </sourceDesc>
        </fileDesc>
    </teiHeader>
    <text>
        <front>      </front>
        <body>
            <head>THE TITLE</head>
            <div type="chapter" part="N" org="uniform" sample="complete">
                <head>CHAPTER I</head>
                <p>Some text.</p>
            </div>
        </body>
    </text>
</TEI>

желаемый, правильный результат:производится :

THE TITLE
CHAPTER I
Some text.
2 голосов
/ 18 июня 2011

Вы можете использовать:

<xsl:strip-space elements="*"/>

и

<xsl:template match="/" xmlns:n="http://www.tei-c.org/ns/1.0">
    <xsl:for-each select="/n:TEI/n:text/n:body/descendant::*/text()">
        <xsl:value-of select="."/>
        <xsl:if test="position() != last()">
            <xsl:text>&#xa;</xsl:text>
        </xsl:if>
    </xsl:for-each>
</xsl:template>

Возвращает:

THE TITLE
CHAPTER I
Some text.
0 голосов
/ 18 июня 2011

Попробуйте сопоставить / TEI / text / body // text ()

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