Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
145 views
in Technique[技术] by (71.8m points)

xml - XSL transform namespace weirdness

I have a generated XML file that looks like the following:

<PublishFACSR xmlns="http://www.ibm.com/maximo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" creationDateTime="2015-07-14T09:23:24-06:00" transLanguage="EN" baseLanguage="EN" messageID="1436887397443667260" maximoVersion="7 5 20140411-2000 V7511--1" event="1">
  <FACSRSet>
    <SR action="Replace">
      <ACCUMULATEDHOLDTIME>0.0</ACCUMULATEDHOLDTIME>
      <ACTLABCOST>0.0</ACTLABCOST>
      <ACTLABHRS>0.0</ACTLABHRS>
      <TICKETID>SR-35102</TICKETID>
      <TICKETUID>39822</TICKETUID>
      <URGENCY changed="1">3</URGENCY>
      <VENDOR />
      <VIRTUALENV>0</VIRTUALENV>
    </SR>
  </FACSRSet>
</PublishFACSR>

I need to replace:
PublishFACSR with SyncFACSR
SR action="Replace" with SR action="AddChange"

I tried using the following XSL

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- This template copies everything that doesn't have a more specific rule -->
<xsl:template match="node()|@*">
  <xsl:copy>
    <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
</xsl:template>
<!-- This template copies and renames PublishMXASSET to SyncMXASSSET -->
<xsl:template match="PublishMXASSET">
  <SyncMXASSSET>
    <xsl:apply-templates/>
  </SyncMXASSSET>
</xsl:template>
</xsl:stylesheet>

it generated the following output:

<SyncFACSR creationDateTime="2015-07-14T12:34:19-06:00" transLanguage="EN" baseLanguage="EN" messageID="1436898852543140608" maximoVersion="7 5 20140411-2000 V7511--1" event="1">
  <FACSRSet xmlns="http://www.ibm.com/maximo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <SR action="Replace">
      <ACCUMULATEDHOLDTIME>0.0</ACCUMULATEDHOLDTIME>
      <ACTLABCOST>0.0</ACTLABCOST>
      <ACTLABHRS>0.0</ACTLABHRS>
      <TICKETID>SR-35102</TICKETID>
      <TICKETUID>39822</TICKETUID>
      <URGENCY>3</URGENCY>
      <VENDOR />
      <VIRTUALENV>0</VIRTUALENV>
    </SR>
  </FACSRSet>
</SyncFACSR>

The biggest problem is that the namespaces have been moved down to the FACSRSet. I assume this is something with the order in which the XML is being generated and the XSL applied.

The output should look like the following:

<SyncFACSR  xmlns="http://www.ibm.com/maximo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" creationDateTime="2015-07-14T12:34:19-06:00" transLanguage="EN" baseLanguage="EN" messageID="1436898852543140608" maximoVersion="7 5 20140411-2000 V7511--1" event="1">
  <FACSRSet>
    <SR action="Replace">
      <ACCUMULATEDHOLDTIME>0.0</ACCUMULATEDHOLDTIME>
      <ACTLABCOST>0.0</ACTLABCOST>
      <ACTLABHRS>0.0</ACTLABHRS>
      <TICKETID>SR-35102</TICKETID>
      <TICKETUID>39822</TICKETUID>
      <URGENCY>3</URGENCY>
      <VENDOR />
      <VIRTUALENV>0</VIRTUALENV>
    </SR>
  </FACSRSet>
</SyncFACSR>

Any ideas on how to resolve.

Oh, and fix the action="AddChange"

thanks

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

First, the XSLT that you show us does not produce the output that you say it does.

Next, the "biggest problem" with the output that you claim is not what you say it is:

The biggest problem is that the namespaces have been moved down to the FACSRSet.

Actually, that's not a problem at all: a namespace declaration can appear anywhere - as long as it's not used outside the scope of the declaring element.

The real problem with your output is that the SyncFACSR element is in no-namespace, while your expected output places it in the "http://www.ibm.com/maximo" namespace - same as the PublishFACSR element that it replaces and all its descendants.

To achieve the expected result, your stylesheet should do:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:max="http://www.ibm.com/maximo" 
xsl:exclude-result-prefixes="max">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

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

<xsl:template match="max:PublishFACSR" >
    <SyncMXASSSET xmlns="http://www.ibm.com/maximo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <xsl:apply-templates select="@*|node()"/>
    </SyncMXASSSET>
</xsl:template>

</xsl:stylesheet>

Finally, to replace SR action="Replace" with SR action="AddChange", add another template:

<xsl:template match="max:SR/@action[.='Replace']" >
    <xsl:attribute name="action">AddChange</xsl:attribute>
</xsl:template>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...