使用XSL缩进XML

时间:2010-12-15 20:31:30

标签: xslt

什么XSL脚本会缩进我的数据?

例如:

 <dtd name="cited">
 <XMLDOC>
 <cited year="2010">
 <case>
 No.&nbsp;275 v. M.N.R. 
 <cite>
 <yr>
 2010 
 <pno cite="20101188">10</pno> 
 </yr>
 </cite>
 </case>
 </cited>
 </XMLDOC>
 <XMLDOC>
 <case>
 Wellesley St.
 <cite>
 <yr>
 2010 
 <pno cite="20105133">9</pno> 
 </yr>
 </cite>
 </case>
 </XMLDOC>
 </dtd>

要:

<dtd name="cited">
  <XMLDOC>
    <cited year="2010"></cited>
    <case>
      No.&nbsp;275 v. M.N.R.
    </case> 
    <cite>
    </cite>
    <yr>
      2010 
    </yr>
    <pno cite="20101188">10</pno> 
  </XMLDOC>
  <XMLDOC>
    <case>
      Wellesley St 
    </case>
    <cite>
    </cite>
    <yr>
      2010 
    </yr>
    <pno cite="20105133">9</pno> 
  </XMLDOC>
</dtd>

谢谢!

相关

sgml to xml convertion

来自评论

  

我想要的是应用正确的   关闭标签,如

<yr></yr>
<pno cite="20101188">10</pno>
     

而不是

<yr>
2010 
<pno cite="20101188">10</pno>
</yr>

3 个答案:

答案 0 :(得分:16)

使用indent="yes声明中指定的<xsl:output>进行简单的身份转换:

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

 <xsl:template match="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

此转换应用于提供的XML文档(未定义的实体&nbsp;替换为其对应的字符实体&#xA0;):

 <dtd name="cited">
 <XMLDOC>
 <cited year="2010">
 <case>
 No.&#xA0;275 v. M.N.R.
 <cite>
 <yr>
 2010
 <pno cite="20101188">10</pno>
 </yr>
 </cite>
 </case>
 </cited>
 </XMLDOC>
 <XMLDOC>
 <case>
 Wellesley St.
 <cite>
 <yr>
 2010
 <pno cite="20105133">9</pno>
 </yr>
 </cite>
 </case>
 </XMLDOC>
 </dtd>

在使用AltovaXML 运行时生成:

<dtd name="cited">
    <XMLDOC>
        <cited year="2010">
            <case>
 No. 275 v. M.N.R.
 <cite>
                    <yr>
 2010
 <pno cite="20101188">10</pno></yr>
                </cite></case>
        </cited>
    </XMLDOC>
    <XMLDOC>
        <case>
 Wellesley St.
 <cite>
                <yr>
 2010
 <pno cite="20105133">9</pno></yr>
            </cite></case>
    </XMLDOC>
</dtd>

使用Saxon 6.5.4运行时,相同的转换产生:

<dtd name="cited">

   <XMLDOC>

      <cited year="2010">

         <case>
 No. 275 v. M.N.R.
 <cite>

               <yr>
 2010
 <pno cite="20101188">10</pno>

               </yr>

            </cite>

         </case>

      </cited>

   </XMLDOC>

   <XMLDOC>

      <case>
 Wellesley St.
 <cite>

            <yr>
 2010
 <pno cite="20105133">9</pno>

            </yr>

         </cite>

      </case>

   </XMLDOC>

</dtd>

因此,输出大不相同,具体取决于使用哪个XSLT 1.0处理器。 Saxon解析并且不会丢弃每个仅限空白的节点,这加上缩进会产生太多的空白区域。

解决方法是使用以下方法显式导致仅删除空白节点:

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

所以,当这个转变时:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

与Saxon针对相同的源XML文档运行,输出现在

<dtd name="cited">
   <XMLDOC>
      <cited year="2010">
         <case>
 No. 275 v. M.N.R.
 <cite>
               <yr>
 2010
 <pno cite="20101188">10</pno>
               </yr>
            </cite>
         </case>
      </cited>
   </XMLDOC>
   <XMLDOC>
      <case>
 Wellesley St.
 <cite>
            <yr>
 2010
 <pno cite="20105133">9</pno>
            </yr>
         </cite>
      </case>
   </XMLDOC>
</dtd>

AltovaXML和许多其他XSLT 1.0处理器(.NET的XslCompiledTransform,XslTransform)也会生成运行最后一次转换的漂亮的缩进输出

<强>更新

就在最近他的评论中,OP泄露了重要的新要求,这使得这个问题完全不仅仅是“缩进”......

  

来自评论:

     

我想要的是应用正确的   关闭标签,如

<yr></yr>  
<pno cite="20101188">10</pno>  
     

而不是

<yr>  
2010   
<pno cite="20101188">10</pno>  
</yr>

这是转换,产生想要的输出:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="yr">
  <yr>
    <xsl:apply-templates select="text()[1]"/>
  </yr>
  <xsl:apply-templates select="*"/>
 </xsl:template>
</xsl:stylesheet>

答案 1 :(得分:1)

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<!-- output xml and indent -->
<xsl:output method="xml" indent="yes"/>
<!-- copy all elements and their attributes -->
<xsl:template match="* | @*">
<xsl:copy><xsl:copy-of select="@*"/><xsl:apply-templates/></xsl:copy>
</xsl:template>
</xsl:stylesheet>

答案 2 :(得分:0)

在Java世界中,Apache Xalan可以提供帮助。您只需在indent标记中添加xslt:indent-amountxmlns:xsltxsl:output个参数即可。

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="xml" encoding="utf-8" indent="yes"
              xslt:indent-amount="3" xmlns:xslt="http://xml.apache.org/xslt" />
...

你可以用Ant运行XSL:

<?xml version="1.0"?>
<project name="My XSL conversion" default="myxsltarget" basedir=".">
  <target name="myxsltarget">
    <xslt basedir="in" destdir="out" extension=".xml" style="myxsl.xsl"/>
  </target>
</project>