XSLT - How to manage CDATA as common content?

六眼飞鱼酱① 提交于 2020-01-06 06:30:07

问题



I am trying to use xslt to render an xml file generated by a software in use at my work. There are some CDATA content in the xml. When I transform it the content of the CDATA is displayed as text but I would like it is only not shown. I found a way to make it empty so that nothing appear while I don't need to exploit it but I have to manage all cases.

My question is : How can I manage all the CDATA content as standard text (accessible with value-of) so that it will not appear while I don't select it for rendering ?

The xml file looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<Domain>
  <Properties>
    <Property id="DOM00000" key="mykey1" value="value1"/>
    <Property id="DOM00001" key="mykey2" value="value2"/>
  </Properties>
  <Tokens>
    <Token name="token1" comment=""><![CDATA[mydata1---blah-blah-blah]]></Token>
    <Token name="token2" comment=""><![CDATA[mydata2---blah-blah-blah]]></Token>
  </Tokens>
  <Resources>
    <Resource name="res1" type="W" current="0">
      <Value><![CDATA[10]]></Value>
    </Resource>
    <Resource name="res2" type="W" current="0">
      <Value><![CDATA[10]]></Value>
    </Resource>
  </Resources>
</Domain>

The xsl file I am using is this one :

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Domain/Properties">
  <table border="1">
    <tr bgcolor="#9acd32">
      <th style="text-align:left">id</th>
      <th style="text-align:left">key</th>
      <th style="text-align:left">value</th>
    </tr>
    <xsl:for-each select="/Domain/Properties/Property">
    <tr>
      <td><xsl:value-of select="@id" /></td>
      <td><xsl:value-of select="@key" /></td>
      <td><xsl:value-of select="@value" /></td>
    </tr>
    </xsl:for-each>
  </table>
  </xsl:template>
  <xsl:template match="/Domain/Tokens/Token">
  </xsl:template>
</xsl:stylesheet> 

Edit Here is what I use :

<form method="POST">
    <label for="xmlfileinput">Fichier XML</label><input type="file" name="myxmlfile" id="xmlfileinput" accept=".xml"><br>
    <label for="xslfileinput">Fichier XSL</label><input type="file" name="myxslfile" id="xslfileinput" accept=".xsl"><br>       
    <input type="button" onclick="handleFiles()">
</form>

function handleFiles(e) {
    var myxmlfile = document.getElementById("xmlfileinput").files;
    var myxslfile = document.getElementById("xslfileinput").files;
    var xmlreader = new FileReader();
    var xslreader = new FileReader();
    xmlreader.onload = function() {
        var xml = new DOMParser().parseFromString(xmlreader.result, "text/xml");
        xslreader.onload = function() {
            var xsl = new DOMParser().parseFromString(xslreader.result, "text/xml");
            if (window.ActiveXObject /*|| xhttp.responseType == "msxml-document"*/)
              {
              ex = xml.transformNode(xsl);
              document.getElementById("example").innerHTML = ex;
              }
            // code for Chrome, Firefox, Opera, etc.
            else if (document.implementation && document.implementation.createDocument)
              {
              xsltProcessor = new XSLTProcessor();
              xsltProcessor.importStylesheet(xsl);
              resultDocument = xsltProcessor.transformToFragment(xml, document);
              while (document.getElementById("example").firstChild) {
document.getElementById("example").removeChild(document.getElementById("example").firstChild);
                }
             document.getElementById("example").appendChild(resultDocument);
              }
        };
        xslreader.readAsText(myxslfile[0]); 
    };
    xmlreader.readAsText(myxmlfile[0]);   
}

In the result with these files the "mydata..." from the Tokens are not shown but the "10" from the Ressources are here.

Thanks


回答1:


I think the problem here is not with the elements containing CDATA sections, but with your template's match pattern.

You start by:

<xsl:template match="/Domain/Properties">

which leaves other children of the root element Domain - namely Tokens and Resources - to be processed by other templates.

You do have a template matching a Token, but not one matching a Resource. So Resources (as well as any other branches your XML might have) is handled by the built-in template rules. This results in all their text (not only text in CDATA sections) being copied to the output.

This has already been mentioned in previous answer. However the solution is not to chase after individual horses, but rather to close the barn door:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/Domain">
  <table border="1">
    <tr bgcolor="#9acd32">
      <th style="text-align:left">id</th>
      <th style="text-align:left">key</th>
      <th style="text-align:left">value</th>
    </tr>
    <xsl:for-each select="Properties/Property">
    <tr>
      <td><xsl:value-of select="@id" /></td>
      <td><xsl:value-of select="@key" /></td>
      <td><xsl:value-of select="@value" /></td>
    </tr>
    </xsl:for-each>
  </table>
</xsl:template>

</xsl:stylesheet> 



回答2:


You have a problem with the built-in template rules, especially

<xsl:template match="*|/">
  <xsl:apply-templates/>
</xsl:template>

It means that all the document is traversed reaching Value elements.

Solution: add another empty template like the one you already have.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Domain/Properties">
  <table border="1">
    <tr bgcolor="#9acd32">
      <th style="text-align:left">id</th>
      <th style="text-align:left">key</th>
      <th style="text-align:left">value</th>
    </tr>
    <xsl:for-each select="/Domain/Properties/Property">
    <tr>
      <td><xsl:value-of select="@id" /></td>
      <td><xsl:value-of select="@key" /></td>
      <td><xsl:value-of select="@value" /></td>
    </tr>
    </xsl:for-each>
  </table>
  </xsl:template>
  <xsl:template match="/Domain/Tokens/Token|/Domain/Resources"/>
</xsl:stylesheet>


来源:https://stackoverflow.com/questions/54832435/xslt-how-to-manage-cdata-as-common-content

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!