开发者

What is the XSLT to write certain node attributes one-to-a-line?

I want an XML stylesheet (XSLT) that will put the attributes of a few, specific, child nodes one-to-a-line. What is the XSLT for this?

I recently asked a related question that someone offered a stylesheet to solve but their stylesheet didn't work for some reason, and I am curious why -- the attributes simply didn't end up one-per-line.

By way of example, my XML might look like this:

<MyXML>
    <NodeA>
       <ChildNode value1='5' value2='6' />
    </NodeA>
    <NodeB>
       <AnotherChildNode value1='5' value2='6' /&开发者_如何学Cgt;
    </NodeB>
    <NodeC>
       <AnotherChildNode value1='5' value2='6' />
    </NodeC>
</MyXML>

And I want a stylesheet that will expand all NodeA's and NodeB's but not NodeCs and make it look like this:

<MyXML>
    <NodeA>
       <ChildNode 
          value1='5' 
          value2='6' />
    </NodeA>
    <NodeB>
       <AnotherChildNode 
          value1='5' 
          value2='6' />
    </NodeB>
    <NodeC>
       <AnotherChildNode value1='5' value2='6' />
    </NodeC>
</MyXML>


I would say XSLT is not the right tool for this job.

XSLTs goal is to transform the data from one format into another.

You can achieve to output newlines for "pretty printing" but you should keep in mind, that this is always a kind of a "hack".

Is there a reason for using XSLT and not $PreferedScriptingLanguage?


XML wise, these are completely identical. So transforming them with XSLT will not change them.

So you might try to

  1. Abuse some XSLT processor (with an identity XSLT transformation) as a "pretty" printer.

  2. Get or write a special pretty printer.

  3. Leave the XML as it is, and adapt your next step in the processing chain to parse the XML instead of parsing values on lines.

I would favour 3.


Hm... If (and only if) the input XML already is indented correctly, you can get away with this:

<xsl:stylesheet 
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
> 
  <xsl:output encoding="utf-8" />

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

  <xsl:template match="NodeA/*|NodeB/*">
    <xsl:variable name="spc" select="preceding-sibling::text()[1]" />
    <xsl:value-of select="concat('&lt;', name())" disable-output-escaping="yes" />
    <xsl:for-each select="@*">
      <xsl:value-of select="concat($spc, '    ', name(), '=&quot;', ., '&quot;')" />
    </xsl:for-each>
    <xsl:choose>
      <xsl:when test="node()">
        <xsl:value-of select="'&gt;'" disable-output-escaping="yes" />
        <xsl:apply-templates select="node()" />
        <xsl:value-of select="concat('&lt;/', name(), '&gt;')" disable-output-escaping="yes" />
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="' /&gt;'" disable-output-escaping="yes" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

</xsl:stylesheet>

But to be honest, I consider this exactly the ugly hack that @echox talks about.

The output ouf the above would be:

<MyXML>
    <NodeA>
       <ChildNode
           value1="5"
           value2="6" />
    </NodeA>
    <NodeB>
       <AnotherChildNode
           value1="5"
           value2="6" />
    </NodeB>
    <NodeC>
       <AnotherChildNode value1="5" value2="6"></AnotherChildNode>
    </NodeC>
</MyXML>
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜