使用XSLT将XML文件的一部分提取为纯文本

时间:2011-06-17 23:48:09

标签: xml xslt

这似乎应该很容易,但是......

我正在尝试使用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 个答案:

答案 0 :(得分:7)

  

我尝试过非常简单的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.

答案 1 :(得分:2)

您可以使用:

<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.

答案 2 :(得分:0)

尝试匹配/ TEI / text / body // text()