首页 > 解决方案 > XSLT 不会在节点上选择简单的移动和替换 text() 节点脚本

问题描述

另外在这个网站上,我得到了很好的 REGEX 帮助(感谢 Andreas!)手动找到这些字段。但我想保留 100% 的原始紧急服务数据,而不是编辑该字段以符合 NEMSIS XSD 作为 REGEX 解决方法和手动主观编辑。

因此,我尝试将任何string-length()大于 50 个字符的 E09_05 或 E09_08 元素(根据 NEMSIS 数据字典的主要投诉和次要投诉)concat()放在叙述或 E13_01 字段的开头。然后,我将用一个简单的<E09_05>See Narrative E13_01 for Chief Complaint</E09_05>(与 E09_08 相同,只是“次要投诉”)来代替这些长期的投诉。

否则,源 XML 中的每个标记、文本和属性都必须原封不动地通过(参见<xsl:template match="@*|node()">脚本末尾的 )。唯一的变化是将长投诉字段移动到各自的叙述中<Record>

同事帮我完成了这个脚本。他们发誓它可以在他们的系统上运行,但我无法让它在我的系统上运行。我尝试了几个 xslt 引擎,包括 msxsl.exe(在我们的环境中需要),但也 - 只是试图让某些东西工作并排除处理器问题 - Notepad++ XML Tools 中的一个,XML Copy 中的那个编辑器,以及 freeformatter.com 上的在线免费版。不过,最后,msxsl 应该是可行的(不是我的选择……这是政府的事情)。

正如我在下面的源文件和 XSLT 文件中所评论的那样,我已经尝试过使用 descendant//或绝对路径等的相对 XPath。没有运气。

源 XML(为简洁起见,被广泛剥离):

<?xml version="1.0" encoding="UTF-8"?>
<EMSDataSet xmlns="http://www.nemsis.org" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.nemsis.org http://www.nemsis.org/media/XSD/EMSDataSet.xsd">
  <Header>
   <!-- SOME STUFF -->
   <Record>
<!-- LOTS OF STUFF -->
       <E08>
        <E08_08>2016</E08_08>
        <E08_10 Lat="42.63" Long="70.68" />
      </E08>
      <E09>
        <E09_04>-5</E09_04>
        <!-- XSLT SHOULD HIT ON THIS AS IT'S AN E09_05 WITH > 50 CHAR string-length() -->
        <E09_05>this one is too long Non-Emergency - PT IS BEING DISCHARGED FROM AGH AFTER BEING ADMITTED FOR FAILURE TO THRIVE AND ALCOHOL WITHDRAWAL</E09_05>
        <E09_11>-5</E09_11>
      </E09>
      <E10>
        <E10_01>-5</E10_01>
        <E10_03>-5</E10_03>
      </E10>
<!-- SOME IN BETWEEN STUFF -->
      <E13>
      <!-- xslt SHOULD concat() THE OVER-LONG E09_05 TEXT HERE AT THE BEGINNING -->
        <E13_01>A8 DISPATCHED TO AGH FOR A 66 Y/O MALE PT BEING DISCHARGED FROM AGH WITH UNSTEADY GAIT --DELETED FOR BREVITY --**A8 CLEAR, WITHOUT INCIDENT**. </E13_01>
      </E13>
    <!-- REST OF THIS DELETED TO SAVE SPACE -->
    </Record>

    <Record>     
     <!-- STUFF DELETED FOR BREVITY - AND THIS E09_05 BELOW SHOULD BE IGNORED BY THE XSLT AND PASSED THROUGH AS IS -->
      <E08>
        <E08_08>2016</E08_08>
        <E08_10 Lat="42.77" Long="70.61" />
      </E08>
      <E09>
        <E09_04>-5</E09_04>
        <E09_05>this length is okay</E09_05>
        <E09_11>-5</E09_11>
      </E09>
      <E10>
        <E10_01>-5</E10_01>
        <E10_03>-5</E10_03>
      </E10>
<!-- DELETED FOR BREVITY -->
      <E13>
        <E13_01>CC= Working as a P/B truck during major snowstorm, on scene, found pt c/o having a syncopal episode.     HXPI= Pt's girlfriend stated that the pt had been outside shoveling snow for approx 1 hour. --DELETED FOR BREVITY OF EXAMPLE </E13_01>
      </E13>
    </Record>
</Header>
</EMSDataSet>

这是 XSLT——其中唯一有效的是第一个模板将空标签保留为空,而不是没有内容的配对(语义上等价,是的,但 NEMSIS XSD 不接受配对标签,只接受空标签),以及通过完整源内容的最后一个模板。

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

<!-- THIS TEMPLATE I FOUND IN A WEB SEARCH TO KEEP EMPTY TAGS AS EMPTY TAGS, WHICH I KNOW ARE SEMANTICALLY EQUIVALENT, BUT THE NEMSIS.XSD WILL NOT ACCEPT PAIRED TAGS, ONLY EMPTY ONES FOR CERTAIN TAGS -->
<xsl:template match="*[not(comment() | processing-instruction() | *)][normalize-space(text()) = '']">
    <xsl:element name="{name()}" namespace="{namespace-uri()}">
        <xsl:for-each select="@* | namespace::*">
            <xsl:copy/>
        </xsl:for-each>
    </xsl:element>
</xsl:template>

<!-- REPLACE E09_05 FIELDS THAT ARE > 50 CHARACTERS WITH THIS "SEE NARRATIVE ..." REPLACEMENT -->
<xsl:template match="E09_05[string-length(.) > 50]">
    <E09_05>See narrative for Chief Complaint</E09_05>
</xsl:template>

<!-- DO THE SAME THING HERE FOR E09_08, I TRIED A FEW DIFFERENT PATH OPTIONS TO GET IT TO "HIT" AND NONE WOULD WORK, E.G., DESCENDANT AXIS //, ABSOLUTE PATH, ETC. -->
<xsl:template match="E09_08[string-length(.) > 50]">
    <E09_08>See narrative for Secondary Complaint</E09_08>
</xsl:template>

<!-- CONCAT THE OVERLONG E09_05 AND/OR E09_08 TEXT TO THE BEGINNING OF THIS E13_01 FIELD -->
<xsl:template match="E13_01/text()">
    <xsl:copy/>
    <xsl:value-of select="concat('ChiefComplaint:',' ', ../../../E09/E09_05[string-length(.) > 50])"/>
    <xsl:value-of select="concat('SecondaryComplaint:',' ', ../../../E09/E09_08[string-length(.) > 50])"/>
</xsl:template>

<!-- identity transform - pass through all other content complete and untouched/unchanged -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

标签: xmlxslt

解决方案


这只是 XSLT/XPath 1.0 常见问题解答的另一个变体,关于如何匹配和/或选择命名空间中的输入元素,为此,您需要在 XSLT 中声明命名空间,并带有您可以选择的前缀和那么您需要使用该前缀来限定 XSLT 匹配模式和 XPath 路径表达式中的任何元素名称;进行一些清理xsl:copy以轻松确保复制的结果元素保留输入名称空间和一些变量以清楚地识别您要引用的元素,并仅插入文本常量,例如ChiefComplaint:您最终得到的条目过长

<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:em="http://www.nemsis.org"
    exclude-result-prefixes="em"
    version="1.0">

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

<!-- REPLACE E09_05 FIELDS THAT ARE > 50 CHARACTERS WITH THIS "SEE NARRATIVE ..." REPLACEMENT -->
<xsl:template match="em:E09_05[string-length(.) > 50]">
    <xsl:copy>See narrative for Chief Complaint</xsl:copy>
</xsl:template>

<!-- DO THE SAME THING HERE FOR E09_08 -->
<xsl:template match="em:E09_08[string-length(.) > 50]">
    <E09_08>See narrative for Secondary Complaint</E09_08>
</xsl:template>

<!-- CONCAT THE OVERLONG E09_05 AND/OR E09_08 TEXT TO THE BEGINNING OF THIS E13_01 FIELD -->
<xsl:template match="em:E13_01/text()">
    <xsl:variable name="e09_05"
      select="ancestor::em:Record/em:E09/em:E09_05[string-length(.) > 50]"/>
    <xsl:if test="$e09_05">
        <xsl:text>ChiefComplaint: </xsl:text>
        <xsl:value-of select="$e09_05"/>
    </xsl:if>
    <xsl:variable name="e09_08"
      select="ancestor::em:Record/em:E09/em:E09_08[string-length(.) > 50]"/>
    <xsl:if test="$e09_08">
        <xsl:text>SecondaryComplaint: </xsl:text>
        <xsl:value-of select="$e09_08"/>
    </xsl:if>
    <xsl:copy/>
</xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/6rexji2


推荐阅读