【问题标题】:Indenting XML using XSL使用 XSL 缩进 XML
【发布时间】:2010-12-15 20:31:29
【问题描述】:

什么 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

来自 cmets

我想要的是应用正确的 结束标签,如

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

而不是

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

【问题讨论】:

  • 这里有一个普遍的误解。您无法仅使用缩进接收从输入中发布的输出。您的问题与其标题不匹配。

标签: xslt


【解决方案1】:

使用在&lt;xsl:output&gt; 声明中指定的indent="yes 的简单身份转换:

<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 文档时(未定义的实体 &amp;nbsp; 被其对应的字符实体 &amp;#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)在运行最后一个转换时也会产生很好的缩进输出

更新

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

来自 cmets:

我想要的是应用正确的 结束标签,如

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

【讨论】:

  • Dimitre,我想要的是应用正确的结束标签,例如 10 而不是 2010 10 感谢您的帮助。
  • @atif:那么您的问题的标题绝对具有误导性。请编辑您的问题以说明此重要信息。你想得到的输出不能简单地通过缩进来完成!
  • @atif:我已更新我的答案以解决您的最新问题。将来,请更好地制定您的问题及其标题。
【解决方案2】:
<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>

【讨论】:

  • 您的样式表与 PI、cmets 不匹配。见Identity transformation
  • Dacracot,你刚刚应用了身份模板,我想要应用正确的结束标签,例如 10 而不是 2010 10 谢谢
  • @atif:此评论应添加到问题中。
  • @atif,他不只是应用身份模板,他在应用缩进时将输入复制到输出。这是您最初要求的。
【解决方案3】:

在 Java 世界中,Apache Xalan 可以提供帮助。您只需将indentxslt:indent-amountxmlns:xslt 参数添加到xsl: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>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-15
    • 1970-01-01
    • 1970-01-01
    • 2013-02-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多